diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/angle/src/libANGLE/renderer/d3d | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/d3d')
252 files changed, 75517 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp new file mode 100755 index 000000000..250162726 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -0,0 +1,188 @@ +// +// Copyright 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. +// + +// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. + +#include "libANGLE/renderer/d3d/BufferD3D.h" + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +unsigned int BufferD3D::mNextSerial = 1; + +BufferD3D::BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory) + : BufferImpl(state), + mFactory(factory), + mStaticIndexBuffer(nullptr), + mStaticBufferCacheTotalSize(0), + mStaticVertexBufferOutOfDate(false), + mUnmodifiedDataUse(0), + mUsage(D3DBufferUsage::STATIC) +{ + updateSerial(); +} + +BufferD3D::~BufferD3D() +{ + SafeDelete(mStaticIndexBuffer); +} + +void BufferD3D::emptyStaticBufferCache() +{ + mStaticVertexBuffers.clear(); + mStaticBufferCacheTotalSize = 0; +} + +void BufferD3D::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferD3D::updateD3DBufferUsage(GLenum usage) +{ + switch (usage) + { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + mUsage = D3DBufferUsage::STATIC; + initializeStaticData(); + break; + + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + case GL_DYNAMIC_DRAW: + mUsage = D3DBufferUsage::DYNAMIC; + break; + default: + UNREACHABLE(); + } +} + +void BufferD3D::initializeStaticData() +{ + if (mStaticVertexBuffers.empty()) + { + auto newStaticBuffer = new StaticVertexBufferInterface(mFactory); + mStaticVertexBuffers.push_back( + std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer)); + } + if (!mStaticIndexBuffer) + { + mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory); + } +} + +StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer() +{ + return mStaticIndexBuffer; +} + +StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute) +{ + if (mStaticVertexBuffers.empty()) + { + // Early out if there aren't any static buffers at all + return nullptr; + } + + // Early out, the attribute can be added to mStaticVertexBuffer. + if (mStaticVertexBuffers.size() == 1 && mStaticVertexBuffers[0]->empty()) + { + return mStaticVertexBuffers[0].get(); + } + + // Cache size limiting: track the total allocated buffer sizes. + size_t currentTotalSize = 0; + + // At this point, see if any of the existing static buffers contains the attribute data + // If there is a cached static buffer that already contains the attribute, then return it + for (const auto &staticBuffer : mStaticVertexBuffers) + { + if (staticBuffer->matchesAttribute(attribute)) + { + return staticBuffer.get(); + } + + currentTotalSize += staticBuffer->getBufferSize(); + } + + // Cache size limiting: Clean-up threshold is four times the base buffer size, with a minimum. + ASSERT(getSize() < std::numeric_limits<size_t>::max() / 4u); + size_t sizeThreshold = std::max(getSize() * 4u, static_cast<size_t>(0x1000u)); + + // If we're past the threshold, clear the buffer cache. Note that this will release buffers + // that are currenly bound, and in an edge case can even translate the same attribute twice + // in the same draw call. It will not delete currently bound buffers, however, because they + // are ref counted. + if (currentTotalSize > sizeThreshold) + { + emptyStaticBufferCache(); + } + + // At this point, we must create a new static buffer for the attribute data. + auto newStaticBuffer = new StaticVertexBufferInterface(mFactory); + newStaticBuffer->setAttribute(attribute); + mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer)); + return newStaticBuffer; +} + +void BufferD3D::invalidateStaticData() +{ + emptyStaticBufferCache(); + + if (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0) + { + SafeDelete(mStaticIndexBuffer); + } + + // If the buffer was created with a static usage then we recreate the static + // buffers so that they are populated the next time we use this buffer. + if (mUsage == D3DBufferUsage::STATIC) + { + initializeStaticData(); + } + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void BufferD3D::promoteStaticUsage(int dataSize) +{ + if (mUsage == D3DBufferUsage::DYNAMIC) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * getSize()) + { + updateD3DBufferUsage(GL_STATIC_DRAW); + } + } +} + +gl::Error BufferD3D::getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) +{ + const uint8_t *data = nullptr; + ANGLE_TRY(getData(&data)); + + *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled); + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h new file mode 100755 index 000000000..fdabe7b7e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -0,0 +1,79 @@ +// +// Copyright 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. +// + +// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl. + +#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/BufferImpl.h" + +#include <stdint.h> +#include <vector> + +namespace rx +{ +class BufferFactoryD3D; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; + +enum class D3DBufferUsage +{ + STATIC, + DYNAMIC, +}; + +class BufferD3D : public BufferImpl +{ + public: + BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory); + virtual ~BufferD3D(); + + unsigned int getSerial() const { return mSerial; } + + virtual size_t getSize() const = 0; + virtual bool supportsDirectBinding() const = 0; + virtual gl::Error markTransformFeedbackUsage() = 0; + virtual gl::Error getData(const uint8_t **outData) = 0; + + StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute); + StaticIndexBufferInterface *getStaticIndexBuffer(); + + virtual void initializeStaticData(); + virtual void invalidateStaticData(); + + void promoteStaticUsage(int dataSize); + + gl::Error getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) override; + + BufferFactoryD3D *getFactory() const { return mFactory; } + D3DBufferUsage getUsage() const { return mUsage; } + + protected: + void updateSerial(); + void updateD3DBufferUsage(GLenum usage); + void emptyStaticBufferCache(); + + BufferFactoryD3D *mFactory; + unsigned int mSerial; + static unsigned int mNextSerial; + + std::vector<std::unique_ptr<StaticVertexBufferInterface>> mStaticVertexBuffers; + StaticIndexBufferInterface *mStaticIndexBuffer; + unsigned int mStaticBufferCacheTotalSize; + unsigned int mStaticVertexBufferOutOfDate; + unsigned int mUnmodifiedDataUse; + D3DBufferUsage mUsage; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp new file mode 100755 index 000000000..6f8d1717c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp @@ -0,0 +1,20 @@ +// +// Copyright 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. +// +// CompilerD3D: +// Implementation of the D3D compiler methods. +// + +#include "libANGLE/renderer/d3d/CompilerD3D.h" + +namespace rx +{ + +CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType) + : mTranslatorOutputType(translatorOutputType) +{ +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h new file mode 100755 index 000000000..8f4334963 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 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. +// + +// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl. + +#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_ +#define LIBANGLE_RENDERER_COMPILERD3D_H_ + +#include "libANGLE/renderer/CompilerImpl.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +class CompilerD3D : public CompilerImpl +{ + public: + CompilerD3D(ShShaderOutput translatorOutputType); + ~CompilerD3D() override {} + + gl::Error release() override { return gl::Error(GL_NO_ERROR); } + ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; } + + private: + ShShaderOutput mTranslatorOutputType; +}; + +} + +#endif // LIBANGLE_RENDERER_COMPILERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp new file mode 100755 index 000000000..f40e6e6ca --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp @@ -0,0 +1,102 @@ +// +// 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. +// + +// DeviceD3D.cpp: D3D implementation of egl::Device + +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +#include "libANGLE/Device.h" +#include "libANGLE/Display.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +DeviceD3D::DeviceD3D() + : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false) +{ +} + +DeviceD3D::~DeviceD3D() +{ +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + { + // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it. + ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice); + device->Release(); + } +#endif +} + +egl::Error DeviceD3D::getDevice(void **outValue) +{ + if (!mIsInitialized) + { + *outValue = nullptr; + return egl::Error(EGL_BAD_DEVICE_EXT); + } + + *outValue = mDevice; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DeviceD3D::initialize(void *device, + EGLint deviceType, + EGLBoolean deviceExternallySourced) +{ + ASSERT(!mIsInitialized); + if (mIsInitialized) + { + return egl::Error(EGL_BAD_DEVICE_EXT); + } + + mDevice = device; + mDeviceType = deviceType; + mDeviceExternallySourced = !!deviceExternallySourced; + +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + { + // Validate the device + IUnknown *iunknown = reinterpret_cast<IUnknown *>(device); + + ID3D11Device *d3dDevice = nullptr; + HRESULT hr = + iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice)); + if (FAILED(hr)) + { + return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT"); + } + + // The QI to ID3D11Device adds a ref to the D3D11 device. + // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the + // D3D11 device. + } + else +#endif + { + ASSERT(!mDeviceExternallySourced); + } + + mIsInitialized = true; + + return egl::Error(EGL_SUCCESS); +} + +EGLint DeviceD3D::getType() +{ + return mDeviceType; +} + +void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const +{ + outExtensions->deviceD3D = true; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h new file mode 100755 index 000000000..1dd997970 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h @@ -0,0 +1,39 @@ +// +// 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. +// + +// DeviceD3D.h: D3D implementation of egl::Device + +#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_ +#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_ + +#include "libANGLE/Device.h" +#include "libANGLE/renderer/DeviceImpl.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ +class DeviceD3D : public DeviceImpl +{ + public: + DeviceD3D(); + ~DeviceD3D() override; + + egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external); + egl::Error getDevice(void **outValue) override; + EGLint getType() override; + void generateExtensions(egl::DeviceExtensions *outExtensions) const override; + bool deviceExternallySourced() override { return mDeviceExternallySourced; } + + private: + void *mDevice; + EGLint mDeviceType; + bool mDeviceExternallySourced; + bool mIsInitialized; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp new file mode 100755 index 000000000..474a08c65 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -0,0 +1,371 @@ +// +// Copyright (c) 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. +// + +// DisplayD3D.cpp: D3D implementation of egl::Display + +#include "libANGLE/renderer/d3d/DisplayD3D.h" + +#include <EGL/eglext.h> + +#include "libANGLE/Context.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" + +#if defined (ANGLE_ENABLE_D3D9) +# include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 + +#if defined (ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 + +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +# define ANGLE_DEFAULT_D3D11 1 +#endif + +namespace rx +{ + +typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*); + +template <typename RendererType> +static RendererD3D *CreateTypedRendererD3D(egl::Display *display) +{ + return new RendererType(display); +} + +egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) +{ + ASSERT(outRenderer != nullptr); + + std::vector<CreateRendererD3DFunction> rendererCreationFunctions; + + if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + const auto &attribMap = display->getAttributeMap(); + EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + + EGLint requestedDisplayType = static_cast<EGLint>( + attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); + +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); + } +# endif + + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +# endif + } + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { +#if defined(ANGLE_ENABLE_D3D11) + if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +#endif + } + else + { + UNIMPLEMENTED(); + } + + egl::Error result(EGL_NOT_INITIALIZED, "No available renderers."); + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) + { + RendererD3D *renderer = rendererCreationFunctions[i](display); + result = renderer->initialize(); + +# if defined(ANGLE_ENABLE_D3D11) + if (renderer->getRendererClass() == RENDERER_D3D11) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", + result.getID(), + NUM_D3D11_INIT_ERRORS); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (renderer->getRendererClass() == RENDERER_D3D9) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", + result.getID(), + NUM_D3D9_INIT_ERRORS); + } +# endif + + if (!result.isError()) + { + *outRenderer = renderer; + break; + } + else + { + // Failed to create the renderer, try the next + SafeDelete(renderer); + } + } + + return result; +} + +DisplayD3D::DisplayD3D() : mRenderer(nullptr) +{ +} + +SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new WindowSurfaceD3D(state, mRenderer, mDisplay, configuration, window, attribs); +} + +SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, 0, nullptr, attribs); +} + +SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, buftype, clientBuffer, + attribs); +} + +SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +ImageImpl *DisplayD3D::createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) +{ + return new EGLImageD3D(mRenderer, target, buffer, attribs); +} + +egl::Error DisplayD3D::getDevice(DeviceImpl **device) +{ + return mRenderer->getEGLDevice(device); +} + +ContextImpl *DisplayD3D::createContext(const gl::ContextState &state) +{ + ASSERT(mRenderer != nullptr); + return mRenderer->createContext(state); +} + +StreamProducerImpl *DisplayD3D::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return mRenderer->createStreamProducerD3DTextureNV12(consumerType, attribs); +} + +egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::initialize(egl::Display *display) +{ + ASSERT(mRenderer == nullptr && display != nullptr); + mDisplay = display; + ANGLE_TRY(CreateRendererD3D(display, &mRenderer)); + return egl::Error(EGL_SUCCESS); +} + +void DisplayD3D::terminate() +{ + SafeDelete(mRenderer); +} + +egl::ConfigSet DisplayD3D::generateConfigs() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->generateConfigs(); +} + +bool DisplayD3D::testDeviceLost() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->testDeviceLost(); +} + +egl::Error DisplayD3D::restoreLostDevice() +{ + // Release surface resources to make the Reset() succeed + for (auto &surface : mSurfaceSet) + { + if (surface->getBoundTexture()) + { + surface->releaseTexImage(EGL_BACK_BUFFER); + } + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + surfaceD3D->releaseSwapChain(); + } + + if (!mRenderer->resetDevice()) + { + return egl::Error(EGL_BAD_ALLOC); + } + + // Restore any surfaces that may have been lost + for (const auto &surface : mSurfaceSet) + { + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + + egl::Error error = surfaceD3D->resetSwapChain(); + if (error.isError()) + { + return error; + } + } + + return egl::Error(EGL_SUCCESS); +} + +bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const +{ + return mRenderer->isValidNativeWindow(window); +} + +egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (buftype) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer), + attribs); + + case EGL_D3D_TEXTURE_ANGLE: + return mRenderer->getD3DTextureInfo(static_cast<IUnknown *>(clientBuffer), nullptr, + nullptr, nullptr); + + default: + return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs); + } +} + +void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + mRenderer->generateDisplayExtensions(outExtensions); +} + +std::string DisplayD3D::getVendorString() const +{ + std::string vendorString = "Google Inc."; + if (mRenderer) + { + vendorString += " " + mRenderer->getVendorString(); + } + + return vendorString; +} + +void DisplayD3D::generateCaps(egl::Caps *outCaps) const +{ + // Display must be initialized to generate caps + ASSERT(mRenderer != nullptr); + + outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT; +} + +egl::Error DisplayD3D::waitClient() const +{ + for (auto &surface : getSurfaceSet()) + { + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + surfaceD3D->checkForOutOfDateSwapChain(); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + if (drawSurface != nullptr) + { + SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface); + drawSurfaceD3D->checkForOutOfDateSwapChain(); + } + + if (readSurface != nullptr) + { + SurfaceD3D *readurfaceD3D = GetImplAs<SurfaceD3D>(readSurface); + readurfaceD3D->checkForOutOfDateSwapChain(); + } + + return egl::Error(EGL_SUCCESS); +} + +gl::Version DisplayD3D::getMaxSupportedESVersion() const +{ + return mRenderer->getMaxSupportedESVersion(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h new file mode 100755 index 000000000..3801a8eb1 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 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. +// + +// DisplayD3D.h: D3D implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ +#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ + +#include "libANGLE/renderer/DisplayImpl.h" +#include "libANGLE/Device.h" + +namespace rx +{ +class RendererD3D; + +class DisplayD3D : public DisplayImpl +{ + public: + DisplayD3D(); + + egl::Error initialize(egl::Display *display) override; + virtual void terminate() override; + + // Surface creation + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + ImageImpl *createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) override; + + ContextImpl *createContext(const gl::ContextState &state) override; + + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; + + egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + egl::Error validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + std::string getVendorString() const override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + gl::Version getMaxSupportedESVersion() const override; + + private: + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + egl::Display *mDisplay; + + rx::RendererD3D *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp new file mode 100755 index 000000000..1946585c1 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -0,0 +1,1087 @@ +// +// Copyright (c) 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. +// +// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation +// + +#include "libANGLE/renderer/d3d/DynamicHLSL.h" + +#include "common/utilities.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/VaryingPacking.h" + +using namespace gl; + +namespace rx +{ + +namespace +{ + +std::string HLSLComponentTypeString(GLenum componentType) +{ + switch (componentType) + { + case GL_UNSIGNED_INT: + return "uint"; + case GL_INT: + return "int"; + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + return "float"; + default: + UNREACHABLE(); + return "not-component-type"; + } +} + +std::string HLSLComponentTypeString(GLenum componentType, int componentCount) +{ + return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : ""); +} + +std::string HLSLMatrixTypeString(GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT2: + return "float2x2"; + case GL_FLOAT_MAT3: + return "float3x3"; + case GL_FLOAT_MAT4: + return "float4x4"; + case GL_FLOAT_MAT2x3: + return "float2x3"; + case GL_FLOAT_MAT3x2: + return "float3x2"; + case GL_FLOAT_MAT2x4: + return "float2x4"; + case GL_FLOAT_MAT4x2: + return "float4x2"; + case GL_FLOAT_MAT3x4: + return "float3x4"; + case GL_FLOAT_MAT4x3: + return "float4x3"; + default: + UNREACHABLE(); + return "not-matrix-type"; + } +} + +std::string HLSLTypeString(GLenum type) +{ + if (gl::IsMatrixType(type)) + { + return HLSLMatrixTypeString(type); + } + + return HLSLComponentTypeString(gl::VariableComponentType(type), + gl::VariableComponentCount(type)); +} + +const PixelShaderOutputVariable *FindOutputAtLocation( + const std::vector<PixelShaderOutputVariable> &outputVariables, + unsigned int location) +{ + for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) + { + if (outputVariables[variableIndex].outputIndex == location) + { + return &outputVariables[variableIndex]; + } + } + + return nullptr; +} + +void WriteArrayString(std::stringstream &strstr, unsigned int i) +{ + static_assert(GL_INVALID_INDEX == UINT_MAX, + "GL_INVALID_INDEX must be equal to the max unsigned int."); + if (i == UINT_MAX) + { + return; + } + + strstr << "["; + strstr << i; + strstr << "]"; +} + +constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; +} // anonymous namespace + +std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize) +{ + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD"); +} + +// DynamicHLSL implementation + +DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) +{ +} + +void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking, + std::stringstream &hlslStream) const +{ + std::string varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize()); + + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &varying = *registerInfo.packedVarying->varying; + ASSERT(!varying.isStruct()); + + // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many + // registers being used. + // For example, if there are N registers, and we have N vec3 varyings and 1 float + // varying, then D3D will pack them into N registers. + // If the float varying has the 'nointerpolation' modifier on it then we would need + // N + 1 registers, and D3D compilation will fail. + + switch (registerInfo.packedVarying->interpolation) + { + case sh::INTERPOLATION_SMOOTH: + hlslStream << " "; + break; + case sh::INTERPOLATION_FLAT: + hlslStream << " nointerpolation "; + break; + case sh::INTERPOLATION_CENTROID: + hlslStream << " centroid "; + break; + default: + UNREACHABLE(); + } + + GLenum transposedType = gl::TransposeMatrixType(varying.type); + GLenum componentType = gl::VariableComponentType(transposedType); + int columnCount = gl::VariableColumnCount(transposedType); + hlslStream << HLSLComponentTypeString(componentType, columnCount); + unsigned int semanticIndex = registerInfo.semanticIndex; + hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n"; + } +} + +std::string DynamicHLSL::generateVertexShaderForInputLayout( + const std::string &sourceShader, + const InputLayout &inputLayout, + const std::vector<sh::Attribute> &shaderAttributes) const +{ + std::stringstream structStream; + std::stringstream initStream; + + structStream << "struct VS_INPUT\n" + << "{\n"; + + int semanticIndex = 0; + unsigned int inputIndex = 0; + + // If gl_PointSize is used in the shader then pointsprites rendering is expected. + // If the renderer does not support Geometry shaders then Instanced PointSprite emulation + // must be used. + bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; + bool useInstancedPointSpriteEmulation = + usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + + // Instanced PointSprite emulation requires additional entries in the + // VS_INPUT structure to support the vertices that make up the quad vertices. + // These values must be in sync with the cooresponding values added during inputlayout creation + // in InputLayoutCache::applyVertexBuffers(). + // + // The additional entries must appear first in the VS_INPUT layout because + // Windows Phone 8 era devices require per vertex data to physically come + // before per instance data in the shader. + if (useInstancedPointSpriteEmulation) + { + structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n" + << " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; + } + + for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex) + { + const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; + if (!shaderAttribute.name.empty()) + { + ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); + VertexFormatType vertexFormatType = + inputIndex < inputLayout.size() ? inputLayout[inputIndex] : VERTEX_FORMAT_INVALID; + + // HLSL code for input structure + if (IsMatrixType(shaderAttribute.type)) + { + // Matrix types are always transposed + structStream << " " + << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); + } + else + { + GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType); + + if (shaderAttribute.name == "gl_InstanceID" || + shaderAttribute.name == "gl_VertexID") + { + // The input types of the instance ID and vertex ID in HLSL (uint) differs from + // the ones in ESSL (int). + structStream << " uint"; + } + else + { + structStream << " " << HLSLComponentTypeString( + componentType, + VariableComponentCount(shaderAttribute.type)); + } + } + + structStream << " " << decorateVariable(shaderAttribute.name) << " : "; + + if (shaderAttribute.name == "gl_InstanceID") + { + structStream << "SV_InstanceID"; + } + else if (shaderAttribute.name == "gl_VertexID") + { + structStream << "SV_VertexID"; + } + else + { + structStream << "TEXCOORD" << semanticIndex; + semanticIndex += VariableRegisterCount(shaderAttribute.type); + } + + structStream << ";\n"; + + // HLSL code for initialization + initStream << " " << decorateVariable(shaderAttribute.name) << " = "; + + // Mismatched vertex attribute to vertex input may result in an undefined + // data reinterpretation (eg for pure integer->float, float->pure integer) + // TODO: issue warning with gl debug info extension, when supported + if (IsMatrixType(shaderAttribute.type) || + (mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0) + { + initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute); + } + else + { + initStream << "input." << decorateVariable(shaderAttribute.name); + } + + initStream << ";\n"; + + inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); + } + } + + structStream << "};\n" + "\n" + "void initAttributes(VS_INPUT input)\n" + "{\n" + << initStream.str() << "}\n"; + + std::string vertexHLSL(sourceShader); + + size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); + vertexHLSL.replace(copyInsertionPos, strlen(VERTEX_ATTRIBUTE_STUB_STRING), structStream.str()); + + return vertexHLSL; +} + +std::string DynamicHLSL::generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector<PixelShaderOutputVariable> &outputVariables, + bool usesFragDepth, + const std::vector<GLenum> &outputLayout) const +{ + const int shaderModel = mRenderer->getMajorShaderModel(); + std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + + std::stringstream declarationStream; + std::stringstream copyStream; + + declarationStream << "struct PS_OUTPUT\n" + "{\n"; + + for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) + { + GLenum binding = outputLayout[layoutIndex]; + + if (binding != GL_NONE) + { + unsigned int location = (binding - GL_COLOR_ATTACHMENT0); + + const PixelShaderOutputVariable *outputVariable = + FindOutputAtLocation(outputVariables, location); + + // OpenGL ES 3.0 spec $4.2.1 + // If [...] not all user-defined output variables are written, the values of fragment + // colors + // corresponding to unwritten variables are similarly undefined. + if (outputVariable) + { + declarationStream << " " + HLSLTypeString(outputVariable->type) << " " + << outputVariable->name << " : " << targetSemantic + << static_cast<int>(layoutIndex) << ";\n"; + + copyStream << " output." << outputVariable->name << " = " + << outputVariable->source << ";\n"; + } + } + } + + if (usesFragDepth) + { + declarationStream << " float gl_Depth : " << depthSemantic << ";\n"; + copyStream << " output.gl_Depth = gl_Depth; \n"; + } + + declarationStream << "};\n" + "\n" + "PS_OUTPUT generateOutput()\n" + "{\n" + " PS_OUTPUT output;\n" + << copyStream.str() << " return output;\n" + "}\n"; + + std::string pixelHLSL(sourceShader); + + size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); + pixelHLSL.replace(outputInsertionPos, strlen(PIXEL_OUTPUT_STUB_STRING), + declarationStream.str()); + + return pixelHLSL; +} + +void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType, + const VaryingPacking &varyingPacking, + std::stringstream &linkStream) const +{ + const auto &builtins = varyingPacking.builtins(shaderType); + ASSERT(builtins.dxPosition.enabled); + linkStream << "{\n" + << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; + + if (builtins.glPosition.enabled) + { + linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; + } + + if (builtins.glFragCoord.enabled) + { + linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; + } + + if (builtins.glPointCoord.enabled) + { + linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; + } + + if (builtins.glPointSize.enabled) + { + linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; + } + + // Do this after gl_PointSize, to potentially combine gl_PointCoord and gl_PointSize into the + // same register. + generateVaryingHLSL(varyingPacking, linkStream); + + linkStream << "};\n"; +} + +bool DynamicHLSL::generateShaderLinkHLSL(const gl::ContextState &data, + const gl::ProgramState &programData, + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const +{ + ASSERT(pixelHLSL->empty() && vertexHLSL->empty()); + + const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader(); + const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader(); + const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL); + const int shaderModel = mRenderer->getMajorShaderModel(); + + // usesViewScale() isn't supported in the D3D9 renderer + ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale()); + + bool useInstancedPointSpriteEmulation = + programMetadata.usesPointSize() && + mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + + // Validation done in the compiler + ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); + + std::stringstream vertexStream; + vertexStream << vertexShaderGL->getTranslatedSource(); + + // Instanced PointSprite emulation requires additional entries originally generated in the + // GeometryShader HLSL. These include pointsize clamp values. + if (useInstancedPointSpriteEmulation) + { + vertexStream << "static float minPointSize = " + << static_cast<int>(data.getCaps().minAliasedPointSize) << ".0f;\n" + << "static float maxPointSize = " + << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n"; + } + + // Add stub string to be replaced when shader is dynamically defined by its layout + vertexStream << "\n" << std::string(VERTEX_ATTRIBUTE_STUB_STRING) << "\n"; + + // Write the HLSL input/output declarations + vertexStream << "struct VS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream); + vertexStream << "\n" + << "VS_OUTPUT main(VS_INPUT input)\n" + << "{\n" + << " initAttributes(input);\n"; + + vertexStream << "\n" + << " gl_main();\n" + << "\n" + << " VS_OUTPUT output;\n"; + + const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX); + + if (vertexBuiltins.glPosition.enabled) + { + vertexStream << " output.gl_Position = gl_Position;\n"; + } + + // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + vertexStream << " output.dx_Position.x = gl_Position.x;\n"; + + if (programMetadata.usesViewScale()) + { + // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f + // when rendering to the default framebuffer. No other values are valid. + vertexStream << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n"; + } + else + { + vertexStream << " output.dx_Position.y = - gl_Position.y;\n"; + } + + vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; + } + else + { + vertexStream << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + " + "dx_ViewAdjust.x * gl_Position.w;\n"; + + // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*, + // then we need to multiply the gl_Position.y by the viewScale. + // usesViewScale() isn't supported when using the D3D9 renderer. + if (programMetadata.usesViewScale() && + (shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "")) + { + vertexStream << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * " + "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"; + } + else + { + vertexStream << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + " + "dx_ViewAdjust.y * gl_Position.w);\n"; + } + + vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; + } + + // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. + if (vertexBuiltins.glPointSize.enabled) + { + vertexStream << " output.gl_PointSize = gl_PointSize;\n"; + } + + if (vertexBuiltins.glFragCoord.enabled) + { + vertexStream << " output.gl_FragCoord = gl_Position;\n"; + } + + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isStruct()); + + vertexStream << " output.v" << registerInfo.semanticIndex << " = "; + + if (packedVarying.isStructField()) + { + vertexStream << decorateVariable(packedVarying.parentStructName) << "."; + } + + vertexStream << decorateVariable(varying.name); + + if (varying.isArray()) + { + WriteArrayString(vertexStream, registerInfo.varyingArrayIndex); + } + + if (VariableRowCount(varying.type) > 1) + { + WriteArrayString(vertexStream, registerInfo.varyingRowIndex); + } + + vertexStream << ";\n"; + } + + // Instanced PointSprite emulation requires additional entries to calculate + // the final output vertex positions of the quad that represents each sprite. + if (useInstancedPointSpriteEmulation) + { + vertexStream << "\n" + << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"; + + vertexStream << " output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / " + "(dx_ViewCoords.x*2)) * output.dx_Position.w;"; + + if (programMetadata.usesViewScale()) + { + // Multiply by ViewScale to invert the rendering when appropriate + vertexStream << " output.dx_Position.y += (-dx_ViewScale.y * " + "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * " + "output.dx_Position.w;"; + } + else + { + vertexStream << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / " + "(dx_ViewCoords.y*2)) * output.dx_Position.w;"; + } + + vertexStream + << " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n"; + + if (programMetadata.usesPointCoord()) + { + vertexStream << "\n" + << " output.gl_PointCoord = input.spriteTexCoord;\n"; + } + } + + // Renderers that enable instanced pointsprite emulation require the vertex shader output member + // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same + // default value used in the generated pixel shader. + if (programMetadata.usesInsertedPointCoordValue()) + { + ASSERT(!useInstancedPointSpriteEmulation); + vertexStream << "\n" + << " output.gl_PointCoord = float2(0.5, 0.5);\n"; + } + + vertexStream << "\n" + << " return output;\n" + << "}\n"; + + std::stringstream pixelStream; + pixelStream << fragmentShaderGL->getTranslatedSource(); + pixelStream << "struct PS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream); + pixelStream << "\n"; + + pixelStream << std::string(PIXEL_OUTPUT_STUB_STRING) << "\n"; + + if (fragmentShader->usesFrontFacing()) + { + if (shaderModel >= 4) + { + pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" + << "{\n"; + } + else + { + pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" + << "{\n"; + } + } + else + { + pixelStream << "PS_OUTPUT main(PS_INPUT input)\n" + << "{\n"; + } + + const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL); + + if (pixelBuiltins.glFragCoord.enabled) + { + pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n"; + + // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. + // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using + // dx_ViewCoords. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + pixelStream << " gl_FragCoord.x = input.dx_Position.x;\n" + << " gl_FragCoord.y = input.dx_Position.y;\n"; + } + else if (shaderModel == 3) + { + pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" + << " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; + } + else + { + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See + // Renderer::setViewport() + pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + " + "dx_ViewCoords.z;\n" + << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + " + "dx_ViewCoords.w;\n"; + } + + if (programMetadata.usesViewScale()) + { + // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account + // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using + // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value. + // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+). + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + // Some assumptions: + // - dx_ViewScale.y = -1.0f when rendering to texture + // - dx_ViewScale.y = +1.0f when rendering to the default framebuffer + // - gl_FragCoord.y has been set correctly above. + // + // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate. + // This involves subtracting the y coordinate from the height of the area being + // rendered to. + // + // First we calculate the height of the area being rendered to: + // render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) * + // gl_FragCoord.y + // + // Note that when we're rendering to default FB, we want our output to be + // equivalent to: + // "gl_FragCoord.y = render_area_height - gl_FragCoord.y" + // + // When we're rendering to a texture, we want our output to be equivalent to: + // "gl_FragCoord.y = gl_FragCoord.y;" + // + // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that + // - When rendering to default FB: scale_factor = 1.0f + // - When rendering to texture: scale_factor = 0.0f + // + // Therefore, we can get our desired output by setting: + // "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y * + // gl_FragCoord.y" + // + // Simplifying, this becomes: + pixelStream + << " gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /" + "(1.0f - input.gl_FragCoord.y * rhw) - dx_ViewScale.y * gl_FragCoord.y;\n"; + } + } + + pixelStream << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + " + "dx_DepthFront.y;\n" + << " gl_FragCoord.w = rhw;\n"; + } + + if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3) + { + pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n" + << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; + } + + if (fragmentShader->usesFrontFacing()) + { + if (shaderModel <= 3) + { + pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + } + else + { + pixelStream << " gl_FrontFacing = isFrontFace;\n"; + } + } + + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isBuiltIn() && !varying.isStruct()); + + // Don't reference VS-only transform feedback varyings in the PS. + // TODO: Consider updating the fragment shader's varyings with a parameter signaling that a + // varying is only used in the vertex shader in MergeVaryings + if (packedVarying.vertexOnly || (!varying.staticUse && !packedVarying.isStructField())) + continue; + + pixelStream << " "; + + if (packedVarying.isStructField()) + { + pixelStream << decorateVariable(packedVarying.parentStructName) << "."; + } + + pixelStream << decorateVariable(varying.name); + + if (varying.isArray()) + { + WriteArrayString(pixelStream, registerInfo.varyingArrayIndex); + } + + GLenum transposedType = TransposeMatrixType(varying.type); + if (VariableRowCount(transposedType) > 1) + { + WriteArrayString(pixelStream, registerInfo.varyingRowIndex); + } + + pixelStream << " = input.v" << registerInfo.semanticIndex; + + switch (VariableColumnCount(transposedType)) + { + case 1: + pixelStream << ".x"; + break; + case 2: + pixelStream << ".xy"; + break; + case 3: + pixelStream << ".xyz"; + break; + case 4: + break; + default: + UNREACHABLE(); + } + pixelStream << ";\n"; + } + + pixelStream << "\n" + << " gl_main();\n" + << "\n" + << " return generateOutput();\n" + << "}\n"; + + *vertexHLSL = vertexStream.str(); + *pixelHLSL = pixelStream.str(); + + return true; +} + +std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const +{ + ASSERT(mRenderer->getMajorShaderModel() >= 4); + + std::stringstream preambleStream; + + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + + preambleStream << "struct GS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream); + preambleStream << "\n" + << "struct GS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream); + preambleStream + << "\n" + << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" + << "{\n" + << " output.gl_Position = input.gl_Position;\n"; + + if (builtins.glPointSize.enabled) + { + preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; + } + + for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList()) + { + preambleStream << " output.v" << varyingRegister.semanticIndex << " = "; + if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT) + { + preambleStream << "flat"; + } + preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n"; + } + + if (builtins.glFragCoord.enabled) + { + preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; + } + + // Only write the dx_Position if we aren't using point sprites + preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n" + << " output.dx_Position = input.dx_Position;\n" + << "#endif // ANGLE_POINT_SPRITE_SHADER\n" + << "}\n"; + + return preambleStream.str(); +} + +std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::ContextState &data, + const gl::ProgramState &programData, + const bool useViewScale, + const std::string &preambleString) const +{ + ASSERT(mRenderer->getMajorShaderModel() >= 4); + + std::stringstream shaderStream; + + const bool pointSprites = (primitiveType == PRIMITIVE_POINTS); + const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos; + + const char *inputPT = nullptr; + const char *outputPT = nullptr; + int inputSize = 0; + int maxVertexOutput = 0; + + switch (primitiveType) + { + case PRIMITIVE_POINTS: + inputPT = "point"; + outputPT = "Triangle"; + inputSize = 1; + maxVertexOutput = 4; + break; + + case PRIMITIVE_LINES: + case PRIMITIVE_LINE_STRIP: + case PRIMITIVE_LINE_LOOP: + inputPT = "line"; + outputPT = "Line"; + inputSize = 2; + maxVertexOutput = 2; + break; + + case PRIMITIVE_TRIANGLES: + case PRIMITIVE_TRIANGLE_STRIP: + case PRIMITIVE_TRIANGLE_FAN: + inputPT = "triangle"; + outputPT = "Triangle"; + inputSize = 3; + maxVertexOutput = 3; + break; + + default: + UNREACHABLE(); + break; + } + + if (pointSprites) + { + shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" + "\n" + "uniform float4 dx_ViewCoords : register(c1);\n"; + + if (useViewScale) + { + shaderStream << "uniform float2 dx_ViewScale : register(c3);\n"; + } + + shaderStream << "\n" + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + << static_cast<int>(data.getCaps().minAliasedPointSize) + << ".0f;\n" + "static float maxPointSize = " + << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n" + << "\n"; + } + + shaderStream << preambleString << "\n" + << "[maxvertexcount(" << maxVertexOutput << ")]\n" + << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], "; + + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) + { + shaderStream << "uint primitiveID : SV_PrimitiveID, "; + } + + shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n" + << "{\n" + << " GS_OUTPUT output = (GS_OUTPUT)0;\n"; + + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) + { + shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n"; + } + else + { + shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n"; + } + + for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex) + { + shaderStream << " copyVertex(output, input[" << vertexIndex + << "], input[lastVertexIndex]);\n"; + + if (!pointSprites) + { + ASSERT(inputSize == maxVertexOutput); + shaderStream << " outStream.Append(output);\n"; + } + } + + if (pointSprites) + { + shaderStream << "\n" + " float4 dx_Position = input[0].dx_Position;\n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, " + "maxPointSize);\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / " + "dx_ViewCoords.y) * dx_Position.w;\n"; + + for (int corner = 0; corner < 4; corner++) + { + if (useViewScale) + { + shaderStream << " \n" + " output.dx_Position = dx_Position + float4(1.0f, " + "-dx_ViewScale.y, 1.0f, 1.0f)" + " * float4(pointSpriteCorners[" + << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + } + else + { + shaderStream << "\n" + " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + } + + if (usesPointCoord) + { + shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner + << "];\n"; + } + + shaderStream << " outStream.Append(output);\n"; + } + } + + shaderStream << " \n" + " outStream.RestartStrip();\n" + "}\n"; + + return shaderStream.str(); +} + +// This method needs to match OutputHLSL::decorate +std::string DynamicHLSL::decorateVariable(const std::string &name) +{ + if (name.compare(0, 3, "gl_") != 0) + { + return "_" + name; + } + + return name; +} + +std::string DynamicHLSL::generateAttributeConversionHLSL( + gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib) const +{ + const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); + std::string attribString = "input." + decorateVariable(shaderAttrib.name); + + // Matrix + if (IsMatrixType(shaderAttrib.type)) + { + return "transpose(" + attribString + ")"; + } + + GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); + int shaderComponentCount = VariableComponentCount(shaderAttrib.type); + + // Perform integer to float conversion (if necessary) + bool requiresTypeConversion = + (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT); + + if (requiresTypeConversion) + { + // TODO: normalization for 32-bit integer formats + ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger); + return "float" + Str(shaderComponentCount) + "(" + attribString + ")"; + } + + // No conversion necessary + return attribString; +} + +void DynamicHLSL::getPixelShaderOutputKey(const gl::ContextState &data, + const gl::ProgramState &programData, + const ProgramD3DMetadata &metadata, + std::vector<PixelShaderOutputVariable> *outPixelShaderKey) +{ + // Two cases when writing to gl_FragColor and using ESSL 1.0: + // - with a 3.0 context, the output color is copied to channel 0 + // - with a 2.0 context, the output color is broadcast to all channels + bool broadcast = metadata.usesBroadcast(data); + const unsigned int numRenderTargets = + (broadcast || metadata.usesMultipleFragmentOuts() ? data.getCaps().maxDrawBuffers : 1); + + if (metadata.getMajorShaderVersion() < 300) + { + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; + renderTargetIndex++) + { + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = GL_FLOAT_VEC4; + outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); + outputKeyVariable.source = + broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; + outputKeyVariable.outputIndex = renderTargetIndex; + + outPixelShaderKey->push_back(outputKeyVariable); + } + } + else + { + const auto &shaderOutputVars = + metadata.getFragmentShader()->getData().getActiveOutputVariables(); + + for (auto outputPair : programData.getOutputVariables()) + { + const VariableLocation &outputLocation = outputPair.second; + const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const std::string &variableName = "out_" + outputLocation.name; + const std::string &elementString = + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); + + ASSERT(outputVariable.staticUse); + + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = outputVariable.type; + outputKeyVariable.name = variableName + elementString; + outputKeyVariable.source = variableName + ArrayString(outputLocation.element); + outputKeyVariable.outputIndex = outputPair.first; + + outPixelShaderKey->push_back(outputKeyVariable); + } + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h new file mode 100755 index 000000000..98e6384e2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -0,0 +1,103 @@ +// +// Copyright (c) 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. +// +// DynamicHLSL.h: Interface for link and run-time HLSL generation +// + +#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ +#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ + +#include <map> +#include <vector> + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Program.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace sh +{ +struct Attribute; +struct ShaderVariable; +} + +namespace gl +{ +class InfoLog; +struct VariableLocation; +struct VertexAttribute; +} + +namespace rx +{ +struct PackedVarying; +class ProgramD3DMetadata; +class ShaderD3D; +class VaryingPacking; + +struct PixelShaderOutputVariable +{ + GLenum type; + std::string name; + std::string source; + size_t outputIndex; +}; + +class DynamicHLSL : angle::NonCopyable +{ + public: + explicit DynamicHLSL(RendererD3D *const renderer); + + std::string generateVertexShaderForInputLayout( + const std::string &sourceShader, + const gl::InputLayout &inputLayout, + const std::vector<sh::Attribute> &shaderAttributes) const; + std::string generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector<PixelShaderOutputVariable> &outputVariables, + bool usesFragDepth, + const std::vector<GLenum> &outputLayout) const; + bool generateShaderLinkHLSL(const gl::ContextState &data, + const gl::ProgramState &programData, + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const; + + std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const; + + std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::ContextState &data, + const gl::ProgramState &programData, + const bool useViewScale, + const std::string &preambleString) const; + + void getPixelShaderOutputKey(const gl::ContextState &data, + const gl::ProgramState &programData, + const ProgramD3DMetadata &metadata, + std::vector<PixelShaderOutputVariable> *outPixelShaderKey); + + private: + RendererD3D *const mRenderer; + + void generateVaryingLinkHLSL(ShaderType shaderType, + const VaryingPacking &varyingPacking, + std::stringstream &linkStream) const; + void generateVaryingHLSL(const VaryingPacking &varyingPacking, + std::stringstream &hlslStream) const; + + // Prepend an underscore + static std::string decorateVariable(const std::string &name); + + std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib) const; +}; + +std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize); +} + +#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp new file mode 100755 index 000000000..30cc4d5ff --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp @@ -0,0 +1,135 @@ +// +// 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. +// + +// EGLImageD3D.cpp: Implements the rx::EGLImageD3D class, the D3D implementation of EGL images + +#include "libANGLE/renderer/d3d/EGLImageD3D.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" + +#include <EGL/eglext.h> + +namespace rx +{ +static gl::ImageIndex GetImageIndex(GLenum target, size_t mip, size_t layer) +{ + if (target == GL_TEXTURE_3D) + { + return gl::ImageIndex::Make3D(static_cast<GLint>(mip), static_cast<GLint>(layer)); + } + else + { + ASSERT(layer == 0); + return gl::ImageIndex::MakeGeneric(target, static_cast<GLint>(mip)); + } +} + +EGLImageD3D::EGLImageD3D(RendererD3D *renderer, + EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) + : mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr) +{ + ASSERT(renderer != nullptr); + ASSERT(buffer != nullptr); + + if (egl::IsTextureTarget(target)) + { + mAttachmentBuffer = GetImplAs<TextureD3D>(GetAs<gl::Texture>(buffer)); + mAttachmentTarget = gl::FramebufferAttachment::Target( + GL_NONE, GetImageIndex(egl_gl::EGLImageTargetToGLTextureTarget(target), + attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0), + attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0))); + } + else if (egl::IsRenderbufferTarget(target)) + { + mAttachmentBuffer = GetImplAs<RenderbufferD3D>(GetAs<gl::Renderbuffer>(buffer)); + mAttachmentTarget = + gl::FramebufferAttachment::Target(GL_NONE, gl::ImageIndex::MakeInvalid()); + } + else + { + UNREACHABLE(); + } +} + +EGLImageD3D::~EGLImageD3D() +{ + SafeDelete(mRenderTarget); +} + +egl::Error EGLImageD3D::initialize() +{ + return egl::Error(EGL_SUCCESS); +} + +gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling) +{ + if (sibling == mBuffer) + { + gl::Error error = copyToLocalRendertarget(); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const +{ + if (mAttachmentBuffer) + { + FramebufferAttachmentRenderTarget *rt = nullptr; + gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt); + if (error.isError()) + { + return error; + } + + *outRT = static_cast<RenderTargetD3D *>(rt); + return gl::Error(GL_NO_ERROR); + } + else + { + ASSERT(mRenderTarget); + *outRT = mRenderTarget; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error EGLImageD3D::copyToLocalRendertarget() +{ + ASSERT(mBuffer != nullptr); + ASSERT(mAttachmentBuffer != nullptr); + ASSERT(mRenderTarget == nullptr); + + RenderTargetD3D *curRenderTarget = nullptr; + gl::Error error = getRenderTarget(&curRenderTarget); + if (error.isError()) + { + return error; + } + + // This only currently applies do D3D11, where it invalidates FBOs with this Image attached. + curRenderTarget->signalDirty(); + + // Clear the source image buffers + mBuffer = nullptr; + mAttachmentBuffer = nullptr; + + return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h new file mode 100755 index 000000000..6ec33e08f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h @@ -0,0 +1,56 @@ +// +// 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. +// + +// EGLImageD3D.h: Defines the rx::EGLImageD3D class, the D3D implementation of EGL images + +#ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ +#define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ + +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/ImageImpl.h" + +namespace egl +{ +class AttributeMap; +} + +namespace rx +{ +class TextureD3D; +class RenderbufferD3D; +class RendererD3D; +class RenderTargetD3D; + +class EGLImageD3D final : public ImageImpl +{ + public: + EGLImageD3D(RendererD3D *renderer, + EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs); + ~EGLImageD3D() override; + + egl::Error initialize() override; + + gl::Error orphan(egl::ImageSibling *sibling) override; + + gl::Error getRenderTarget(RenderTargetD3D **outRT) const; + + private: + gl::Error copyToLocalRendertarget(); + + RendererD3D *mRenderer; + + egl::ImageSibling *mBuffer; + + gl::FramebufferAttachment::Target mAttachmentTarget; + FramebufferAttachmentObjectImpl *mAttachmentBuffer; + + RenderTargetD3D *mRenderTarget; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp new file mode 100755 index 000000000..cc8bb0ea7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -0,0 +1,381 @@ +// +// Copyright 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. +// + +// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes. + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +#include "common/BitSetIterator.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/ContextImpl.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" + +namespace rx +{ + +namespace +{ + +ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) +{ + ClearParameters clearParams; + memset(&clearParams, 0, sizeof(ClearParameters)); + + const auto &blendState = state.getBlendState(); + + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = false; + } + clearParams.colorFClearValue = state.getColorClearValue(); + clearParams.colorClearType = GL_FLOAT; + clearParams.colorMaskRed = blendState.colorMaskRed; + clearParams.colorMaskGreen = blendState.colorMaskGreen; + clearParams.colorMaskBlue = blendState.colorMaskBlue; + clearParams.colorMaskAlpha = blendState.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthClearValue = state.getDepthClearValue(); + clearParams.clearStencil = false; + clearParams.stencilClearValue = state.getStencilClearValue(); + clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask; + clearParams.scissorEnabled = state.isScissorTestEnabled(); + clearParams.scissor = state.getScissor(); + + const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); + if (mask & GL_COLOR_BUFFER_BIT) + { + if (framebufferObject->hasEnabledDrawBuffer()) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = true; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL) + { + clearParams.clearDepth = true; + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (framebufferObject->getStencilbuffer() != NULL && + framebufferObject->getStencilbuffer()->getStencilSize() > 0) + { + clearParams.clearStencil = true; + } + } + + return clearParams; +} + +} + +FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer) + : FramebufferImpl(data), mRenderer(renderer) +{ +} + +FramebufferD3D::~FramebufferD3D() +{ +} + +gl::Error FramebufferD3D::clear(ContextImpl *context, GLbitfield mask) +{ + ClearParameters clearParams = GetClearParameters(context->getGLState(), mask); + return clearImpl(context, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) +{ + // glClearBufferfv can be called to clear the color buffer or depth buffer + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); + } + clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_FLOAT; + } + + if (buffer == GL_DEPTH) + { + clearParams.clearDepth = true; + clearParams.depthClearValue = values[0]; + } + + return clearImpl(context, clearParams); +} + +gl::Error FramebufferD3D::clearBufferuiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) +{ + // glClearBufferuiv can only be called to clear a color buffer + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); + } + clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_UNSIGNED_INT; + + return clearImpl(context, clearParams); +} + +gl::Error FramebufferD3D::clearBufferiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLint *values) +{ + // glClearBufferiv can be called to clear the color buffer or stencil buffer + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); + } + clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_INT; + } + + if (buffer == GL_STENCIL) + { + clearParams.clearStencil = true; + clearParams.stencilClearValue = values[1]; + } + + return clearImpl(context, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfi(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) +{ + // glClearBufferfi can only be called to clear a depth stencil buffer + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + clearParams.clearDepth = true; + clearParams.depthClearValue = depth; + clearParams.clearStencil = true; + clearParams.stencilClearValue = stencil; + + return clearImpl(context, clearParams); +} + +GLenum FramebufferD3D::getImplementationColorReadFormat() const +{ + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.getReadPixelsFormat(); +} + +GLenum FramebufferD3D::getImplementationColorReadType() const +{ + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.getReadPixelsType(); +} + +gl::Error FramebufferD3D::readPixels(ContextImpl *context, + const gl::Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const +{ + const gl::PixelPackState &packState = context->getGLState().getPackState(); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + + GLuint outputPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, packState.alignment, packState.rowLength), + outputPitch); + GLuint outputSkipBytes = 0; + ANGLE_TRY_RESULT(formatInfo.computeSkipBytes(outputPitch, 0, packState, false), + outputSkipBytes); + + return readPixelsImpl(area, format, type, outputPitch, packState, + reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); +} + +gl::Error FramebufferD3D::blit(ContextImpl *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) +{ + const auto &glState = context->getGLState(); + const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer(); + bool blitRenderTarget = false; + if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr && + mState.getFirstColorAttachment() != nullptr) + { + blitRenderTarget = true; + } + + bool blitStencil = false; + if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr && + mState.getStencilAttachment() != nullptr) + { + blitStencil = true; + } + + bool blitDepth = false; + if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr && + mState.getDepthAttachment() != nullptr) + { + blitDepth = true; + } + + if (blitRenderTarget || blitDepth || blitStencil) + { + const gl::Rectangle *scissor = + glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr; + gl::Error error = blitImpl(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, + blitStencil, filter, sourceFramebuffer); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool FramebufferD3D::checkStatus() const +{ + // if we have both a depth and stencil buffer, they must refer to the same object + // since we only support packed_depth_stencil and not separate depth and stencil + if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr && + mState.getDepthStencilAttachment() == nullptr) + { + return false; + } + + // D3D11 does not allow for overlapping RenderTargetViews + if (!mState.colorAttachmentsAreUniqueImages()) + { + return false; + } + + // D3D requires all render targets to have the same dimensions. + if (!mState.attachmentsHaveSameDimensions()) + { + return false; + } + + return true; +} + +void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) +{ + bool invalidateColorAttachmentCache = false; + + if (!mColorAttachmentsForRender.valid()) + { + invalidateColorAttachmentCache = true; + } + + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 && + dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) || + dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS) + { + invalidateColorAttachmentCache = true; + } + } + + if (!invalidateColorAttachmentCache) + { + return; + } + + // Does not actually free memory + gl::AttachmentList colorAttachmentsForRender; + + const auto &colorAttachments = mState.getColorAttachments(); + const auto &drawBufferStates = mState.getDrawBufferStates(); + const auto &workarounds = mRenderer->getWorkarounds(); + + for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex) + { + GLenum drawBufferState = drawBufferStates[attachmentIndex]; + const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex]; + + if (colorAttachment.isAttached() && drawBufferState != GL_NONE) + { + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + colorAttachmentsForRender.push_back(&colorAttachment); + } + else if (!workarounds.mrtPerfWorkaround) + { + colorAttachmentsForRender.push_back(nullptr); + } + } + + mColorAttachmentsForRender = std::move(colorAttachmentsForRender); +} + +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const +{ + ASSERT(mColorAttachmentsForRender.valid()); + return mColorAttachmentsForRender.value(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h new file mode 100755 index 000000000..e56ee7c0b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -0,0 +1,130 @@ +// +// Copyright 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. +// + +// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes. + +#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ + +#include <vector> +#include <cstdint> + +#include "common/Color.h" +#include "common/Optional.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace gl +{ +class FramebufferAttachment; +struct PixelPackState; + +typedef std::vector<const FramebufferAttachment *> AttachmentList; + +} + +namespace rx +{ +class RendererD3D; +class RenderTargetD3D; +struct WorkaroundsD3D; + +struct ClearParameters +{ + bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + gl::ColorF colorFClearValue; + gl::ColorI colorIClearValue; + gl::ColorUI colorUIClearValue; + GLenum colorClearType; + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + bool clearDepth; + float depthClearValue; + + bool clearStencil; + GLint stencilClearValue; + GLuint stencilWriteMask; + + bool scissorEnabled; + gl::Rectangle scissor; +}; + +class FramebufferD3D : public FramebufferImpl +{ + public: + FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer); + virtual ~FramebufferD3D(); + + gl::Error clear(ContextImpl *impl, GLbitfield mask) override; + gl::Error clearBufferfv(ContextImpl *impl, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) override; + gl::Error clearBufferuiv(ContextImpl *impl, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) override; + gl::Error clearBufferiv(ContextImpl *impl, + GLenum buffer, + GLint drawbuffer, + const GLint *values) override; + gl::Error clearBufferfi(ContextImpl *impl, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) override; + + GLenum getImplementationColorReadFormat() const override; + GLenum getImplementationColorReadType() const override; + gl::Error readPixels(ContextImpl *impl, + const gl::Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const override; + + gl::Error blit(ContextImpl *impl, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) override; + + bool checkStatus() const override; + + void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; + + const gl::AttachmentList &getColorAttachmentsForRender() const; + + private: + virtual gl::Error clearImpl(ContextImpl *impl, const ClearParameters &clearParams) = 0; + + virtual gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const = 0; + + virtual gl::Error blitImpl(const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) = 0; + + virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0; + + RendererD3D *mRenderer; + Optional<gl::AttachmentList> mColorAttachmentsForRender; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp new file mode 100755 index 000000000..305b6c4e4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -0,0 +1,333 @@ +// +// Copyright 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. +// + +#include "libANGLE/renderer/d3d/HLSLCompiler.h" + +#include "common/utilities.h" +#include "libANGLE/Program.h" +#include "libANGLE/features.h" +#include "libANGLE/histogram_macros.h" +#include "third_party/trace_event/trace_event.h" + +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED +namespace +{ +#ifdef CREATE_COMPILER_FLAG_INFO + #undef CREATE_COMPILER_FLAG_INFO +#endif + +#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } + +struct CompilerFlagInfo +{ + UINT mFlag; + const char *mName; +}; + +CompilerFlagInfo CompilerFlagInfos[] = +{ + // NOTE: The data below is copied from d3dcompiler.h + // If something changes there it should be changed here as well + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG), // (1 << 0) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION), // (1 << 1) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION), // (1 << 2) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR), // (1 << 3) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR), // (1 << 4) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION), // (1 << 5) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT), // (1 << 6) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT), // (1 << 7) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER), // (1 << 8) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL), // (1 << 9) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL), // (1 << 10) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS), // (1 << 11) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS), // (1 << 13) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0), // (1 << 14) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1), // 0 + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2), // ((1 << 14) | (1 << 15)) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3), // (1 << 15) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16), // (1 << 16) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17), // (1 << 17) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS) // (1 << 18) +}; + +#undef CREATE_COMPILER_FLAG_INFO + +bool IsCompilerFlagSet(UINT mask, UINT flag) +{ + bool isFlagSet = IsMaskFlagSet(mask, flag); + + switch(flag) + { + case D3DCOMPILE_OPTIMIZATION_LEVEL0: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3)); + + case D3DCOMPILE_OPTIMIZATION_LEVEL1: + return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0); + + case D3DCOMPILE_OPTIMIZATION_LEVEL3: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0)); + + default: + return isFlagSet; + } +} +} // anonymous namespace +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED + +namespace rx +{ + +CompileConfig::CompileConfig() + : flags(0), + name() +{ +} + +CompileConfig::CompileConfig(UINT flags, const std::string &name) + : flags(flags), + name(name) +{ +} + +HLSLCompiler::HLSLCompiler() + : mInitialized(false), + mD3DCompilerModule(nullptr), + mD3DCompileFunc(nullptr), + mD3DDisassembleFunc(nullptr) +{ +} + +HLSLCompiler::~HLSLCompiler() +{ + release(); +} + +gl::Error HLSLCompiler::initialize() +{ + if (mInitialized) + { + return gl::Error(GL_NO_ERROR); + } + + TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize"); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) + // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. + static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) + { + break; + } + } +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL); + } + + if (!mD3DCompilerModule) + { + ERR("D3D compiler module not found."); + return gl::Error(GL_OUT_OF_MEMORY, "D3D compiler module not found."); + } + + mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); + + mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(GetProcAddress(mD3DCompilerModule, "D3DDisassemble")); + ASSERT(mD3DDisassembleFunc); + +#else + // D3D Shader compiler is linked already into this module, so the export + // can be directly assigned. + mD3DCompilerModule = nullptr; + mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile); + mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(D3DDisassemble); +#endif + + if (mD3DCompileFunc == nullptr) + { + return gl::Error(GL_OUT_OF_MEMORY, "Error finding D3DCompile entry point."); + } + + mInitialized = true; + return gl::Error(GL_NO_ERROR); +} + +void HLSLCompiler::release() +{ + if (mInitialized) + { + FreeLibrary(mD3DCompilerModule); + mD3DCompilerModule = nullptr; + mD3DCompileFunc = nullptr; + mD3DDisassembleFunc = nullptr; + mInitialized = false; + } +} + +gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + ASSERT(mD3DCompilerModule); +#endif + ASSERT(mD3DCompileFunc); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (gl::DebugAnnotationsActive()) + { + std::string sourcePath = getTempPath(); + std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } +#endif + + const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr; + + for (size_t i = 0; i < configs.size(); ++i) + { + ID3DBlob *errorMessage = nullptr; + ID3DBlob *binary = nullptr; + HRESULT result = S_OK; + + { + TRACE_EVENT0("gpu.angle", "D3DCompile"); + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3DCompileMS"); + result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr, + "main", profile.c_str(), configs[i].flags, 0, &binary, + &errorMessage); + } + + if (errorMessage) + { + std::string message = reinterpret_cast<const char*>(errorMessage->GetBufferPointer()); + SafeRelease(errorMessage); + + infoLog.appendSanitized(message.c_str()); + TRACE("\n%s", hlsl.c_str()); + TRACE("\n%s", message.c_str()); + + if ((message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" + message.find("error X4014:") != std::string::npos) && // "cannot have gradient operations inside loops with divergent flow control", + // even though it is counter-intuitive to disable unrolling for this error, + // some very long shaders have trouble deciding which loops to unroll and + // turning off forced unrolls allows them to compile properly. + macros != nullptr) + { + macros = nullptr; // Disable [loop] and [flatten] + + // Retry without changing compiler flags + i--; + continue; + } + } + + if (SUCCEEDED(result)) + { + *outCompiledBlob = binary; + + (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; + +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED + (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; + (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; + for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) + { + if (IsCompilerFlagSet(configs[i].flags, CompilerFlagInfos[fIx].mFlag)) + { + (*outDebugInfo) += std::string("// ") + CompilerFlagInfos[fIx].mName + "\n"; + } + } + + (*outDebugInfo) += "// Macros:\n"; + if (macros == nullptr) + { + (*outDebugInfo) += "// - : -\n"; + } + else + { + for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt) + { + (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n"; + } + } + + std::string disassembly; + error = disassembleBinary(binary, &disassembly); + if (error.isError()) + { + return error; + } + (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n"; +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED + return gl::Error(GL_NO_ERROR); + } + + if (result == E_OUTOFMEMORY) + { + *outCompiledBlob = nullptr; + return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); + } + + infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. (" + << profile << ")"; + + if (i + 1 < configs.size()) + { + infoLog << " Retrying with " << configs[i + 1].name; + } + } + + // None of the configurations succeeded in compiling this shader but the compiler is still intact + *outCompiledBlob = nullptr; + return gl::Error(GL_NO_ERROR); +} + +gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + // Retrieve disassembly + UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; + ID3DBlob *disassembly = nullptr; + pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc); + LPCVOID buffer = shaderBinary->GetBufferPointer(); + SIZE_T bufSize = shaderBinary->GetBufferSize(); + HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly); + + if (SUCCEEDED(result)) + { + *disassemblyOut = std::string(reinterpret_cast<const char*>(disassembly->GetBufferPointer())); + } + else + { + *disassemblyOut = ""; + } + + SafeRelease(disassembly); + + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h new file mode 100755 index 000000000..3c0d2adca --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h @@ -0,0 +1,56 @@ +#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ +#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" +#include "common/platform.h" + +#include <vector> +#include <string> + +namespace gl +{ +class InfoLog; +} + +namespace rx +{ + +struct CompileConfig +{ + UINT flags; + std::string name; + + CompileConfig(); + CompileConfig(UINT flags, const std::string &name); +}; + +class HLSLCompiler : angle::NonCopyable +{ + public: + HLSLCompiler(); + ~HLSLCompiler(); + + void release(); + + // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob + // even if no GL errors are returned. + gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo); + + gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut); + + private: + gl::Error initialize(); + + bool mInitialized; + HMODULE mD3DCompilerModule; + pD3DCompile mD3DCompileFunc; + pD3DDisassemble mD3DDisassembleFunc; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp new file mode 100755 index 000000000..c9581ccaa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,42 @@ +// +// Copyright (c) 2002-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. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libANGLE/renderer/d3d/ImageD3D.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() + : mWidth(0), + mHeight(0), + mDepth(0), + mInternalFormat(GL_NONE), + mRenderable(false), + mTarget(GL_NONE), + mDirty(false) +{ +} + +GLenum +ImageD3D::getSizedInputFormat(GLenum inputType) const +{ + const auto &internalFormat = gl::GetInternalFormatInfo(mInternalFormat); + const auto &unsizedInternalFormat = internalFormat.format; + const auto &sizedInputFormat = gl::GetSizedInternalFormat(unsizedInternalFormat, inputType); + return sizedInputFormat; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h new file mode 100755 index 000000000..79840c15b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h @@ -0,0 +1,88 @@ +// +// Copyright (c) 2002-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. +// + +// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_ +#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_ + +#include "common/debug.h" + +#include "libANGLE/Error.h" + +namespace gl +{ +class Framebuffer; +struct ImageIndex; +struct Box; +struct Extents; +struct Offset; +struct Rectangle; +struct PixelUnpackState; +} + +namespace rx +{ +class TextureStorage; +class RendererD3D; +class RenderTargetD3D; + +class ImageD3D : angle::NonCopyable +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } + + void markDirty() { mDirty = true; } + void markClean() { mDirty = false; } + virtual bool isDirty() const = 0; + + virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; + + GLenum getSizedInputFormat(GLenum inputType) const; + + virtual gl::Error loadData(const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) = 0; + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0; + + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; + + virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, + TextureStorage *source) = 0; + virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) = 0; + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + bool mRenderable; + GLenum mTarget; + + bool mDirty; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp new file mode 100755 index 000000000..677b8bb24 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp @@ -0,0 +1,196 @@ +// +// Copyright (c) 2002-2012 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. +// + +// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +unsigned int IndexBuffer::mNextSerial = 1; + +IndexBuffer::IndexBuffer() +{ + updateSerial(); +} + +IndexBuffer::~IndexBuffer() +{ +} + +unsigned int IndexBuffer::getSerial() const +{ + return mSerial; +} + +void IndexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + + +IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic) +{ + mIndexBuffer = factory->createIndexBuffer(); + + mDynamic = dynamic; + mWritePosition = 0; +} + +IndexBufferInterface::~IndexBufferInterface() +{ + if (mIndexBuffer) + { + delete mIndexBuffer; + } +} + +GLenum IndexBufferInterface::getIndexType() const +{ + return mIndexBuffer->getIndexType(); +} + +unsigned int IndexBufferInterface::getBufferSize() const +{ + return mIndexBuffer->getBufferSize(); +} + +unsigned int IndexBufferInterface::getSerial() const +{ + return mIndexBuffer->getSerial(); +} + +gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset) +{ + // Protect against integer overflow + if (mWritePosition + size < mWritePosition) + { + return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow."); + } + + gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory); + if (error.isError()) + { + if (outMappedMemory) + { + *outMappedMemory = NULL; + } + return error; + } + + if (streamOffset) + { + *streamOffset = mWritePosition; + } + + mWritePosition += size; + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBufferInterface::unmapBuffer() +{ + return mIndexBuffer->unmapBuffer(); +} + +IndexBuffer * IndexBufferInterface::getIndexBuffer() const +{ + return mIndexBuffer; +} + +unsigned int IndexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void IndexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +gl::Error IndexBufferInterface::discard() +{ + return mIndexBuffer->discard(); +} + +gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) +{ + if (mIndexBuffer->getBufferSize() == 0) + { + return mIndexBuffer->initialize(bufferSize, indexType, mDynamic); + } + else + { + return mIndexBuffer->setSize(bufferSize, indexType); + } +} + +StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, true) +{ +} + +StreamingIndexBufferInterface::~StreamingIndexBufferInterface() +{ +} + +gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curBufferSize = getBufferSize(); + unsigned int writePos = getWritePosition(); + if (size > curBufferSize) + { + gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + else if (writePos + size > curBufferSize || writePos + size < writePos) + { + gl::Error error = discard(); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + + return gl::Error(GL_NO_ERROR); +} + + +StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, false) +{ +} + +StaticIndexBufferInterface::~StaticIndexBufferInterface() +{ +} + +gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + return setBufferSize(size, indexType); + } + else if (curSize >= size && indexType == getIndexType()) + { + return gl::Error(GL_NO_ERROR); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h new file mode 100755 index 000000000..0b7b28ddf --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h @@ -0,0 +1,100 @@ +// +// Copyright (c) 2002-2012 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. +// + +// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#ifndef LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +namespace rx +{ +class BufferFactoryD3D; + +class IndexBuffer : angle::NonCopyable +{ + public: + IndexBuffer(); + virtual ~IndexBuffer(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual gl::Error unmapBuffer() = 0; + + virtual gl::Error discard() = 0; + + virtual GLenum getIndexType() const = 0; + virtual unsigned int getBufferSize() const = 0; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType) = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class IndexBufferInterface : angle::NonCopyable +{ + public: + IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic); + virtual ~IndexBufferInterface(); + + virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + + GLenum getIndexType() const; + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); + gl::Error unmapBuffer(); + + IndexBuffer *getIndexBuffer() const; + + protected: + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + gl::Error discard(); + + gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType); + + private: + IndexBuffer *mIndexBuffer; + + unsigned int mWritePosition; + bool mDynamic; +}; + +class StreamingIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory); + ~StreamingIndexBufferInterface(); + + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; +}; + +class StaticIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StaticIndexBufferInterface(BufferFactoryD3D *factory); + ~StaticIndexBufferInterface(); + + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp new file mode 100755 index 000000000..474c77fce --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -0,0 +1,354 @@ +// +// Copyright (c) 2002-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. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libANGLE/renderer/d3d/IndexDataManager.h" + +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/formatutils.h" + +namespace rx +{ + +namespace +{ + +template <typename InputT, typename DestT> +void ConvertIndexArray(const void *input, + GLenum sourceType, + void *output, + GLenum destinationType, + GLsizei count, + bool usePrimitiveRestartFixedIndex) +{ + const InputT *in = static_cast<const InputT *>(input); + DestT *out = static_cast<DestT *>(output); + + if (usePrimitiveRestartFixedIndex) + { + InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType)); + DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType)); + for (GLsizei i = 0; i < count; i++) + { + out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i])); + } + } + else + { + for (GLsizei i = 0; i < count; i++) + { + out[i] = static_cast<DestT>(in[i]); + } + } +} + +void ConvertIndices(GLenum sourceType, + GLenum destinationType, + const void *input, + GLsizei count, + void *output, + bool usePrimitiveRestartFixedIndex) +{ + if (sourceType == destinationType) + { + const gl::Type &typeInfo = gl::GetTypeInfo(destinationType); + memcpy(output, input, count * typeInfo.bytes); + return; + } + + if (sourceType == GL_UNSIGNED_BYTE) + { + ASSERT(destinationType == GL_UNSIGNED_SHORT); + ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); + } + else if (sourceType == GL_UNSIGNED_SHORT) + { + ASSERT(destinationType == GL_UNSIGNED_INT); + ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); + } + else UNREACHABLE(); +} + +gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, + const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + unsigned int *offset) +{ + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", + count, dstTypeInfo.bytes); + } + + unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift; + gl::Error error = buffer->reserveBufferSpace(bufferSizeRequired, dstType); + if (error.isError()) + { + return error; + } + + void *output = nullptr; + error = buffer->mapBuffer(bufferSizeRequired, &output, offset); + if (error.isError()) + { + return error; + } + + ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex); + + error = buffer->unmapBuffer(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +} // anonymous namespace + +IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) + : mFactory(factory), + mRendererClass(rendererClass), + mStreamingBufferShort(nullptr), + mStreamingBufferInt(nullptr) +{ +} + +IndexDataManager::~IndexDataManager() +{ + SafeDelete(mStreamingBufferShort); + SafeDelete(mStreamingBufferInt); +} + +// This function translates a GL-style indices into DX-style indices, with their description +// returned in translated. +// GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not +// possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer +// (Case 2), in a format supported by DX (subcase a) then all is good. +// When we have a buffer with an unsupported format (subcase b) then we need to do some translation: +// we will start by falling back to streaming, and after a while will start using a static translated +// copy of the index buffer. +gl::Error IndexDataManager::prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + bool primitiveRestartFixedIndexEnabled) +{ + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + bool hasPrimitiveRestartIndex = + translated->indexRange.vertexIndexCount < static_cast<size_t>(count) || + translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType); + bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 && + !primitiveRestartFixedIndexEnabled && + hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT; + + // We should never have to deal with MAX_UINT indices, since we restrict it via + // MAX_ELEMENT_INDEX. + ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled && + hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT)); + + const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ? + GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + + const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType); + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr; + + translated->indexType = dstType; + translated->srcIndexData.srcBuffer = buffer; + translated->srcIndexData.srcIndices = indices; + translated->srcIndexData.srcIndexType = srcType; + translated->srcIndexData.srcCount = count; + + // Case 1: the indices are passed by pointer, which forces the streaming of index data + if (glBuffer == nullptr) + { + translated->storage = nullptr; + return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled, + translated); + } + + // Case 2: the indices are already in a buffer + unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); + ASSERT(srcTypeInfo.bytes * static_cast<unsigned int>(count) + offset <= buffer->getSize()); + + bool offsetAligned; + switch (srcType) + { + case GL_UNSIGNED_BYTE: offsetAligned = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: offsetAligned = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: offsetAligned = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); offsetAligned = false; + } + + // Case 2a: the buffer can be used directly + if (offsetAligned && buffer->supportsDirectBinding() && + dstType == srcType && !primitiveRestartWorkaround) + { + translated->storage = buffer; + translated->indexBuffer = nullptr; + translated->serial = buffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->startOffset = offset; + return gl::Error(GL_NO_ERROR); + } + else + { + translated->storage = nullptr; + } + + // Case 2b: use a static translated copy or fall back to streaming + StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer(); + + bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0; + bool staticBufferUsable = staticBuffer && + offsetAligned && staticBuffer->getIndexType() == dstType; + + if (staticBufferInitialized && !staticBufferUsable) + { + buffer->invalidateStaticData(); + staticBuffer = nullptr; + } + + if (staticBuffer == nullptr || !offsetAligned) + { + const uint8_t *bufferData = nullptr; + gl::Error error = buffer->getData(&bufferData); + if (error.isError()) + { + return error; + } + ASSERT(bufferData != nullptr); + + error = streamIndexData(bufferData + offset, count, srcType, dstType, + primitiveRestartFixedIndexEnabled, translated); + if (error.isError()) + { + return error; + } + buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift); + } + else + { + if (!staticBufferInitialized) + { + const uint8_t *bufferData = nullptr; + gl::Error error = buffer->getData(&bufferData); + if (error.isError()) + { + return error; + } + ASSERT(bufferData != nullptr); + + unsigned int convertCount = + static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift; + error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType, + primitiveRestartFixedIndexEnabled, nullptr); + if (error.isError()) + { + return error; + } + } + ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType); + + translated->indexBuffer = staticBuffer->getIndexBuffer(); + translated->serial = staticBuffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexDataManager::streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated) +{ + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + IndexBufferInterface *indexBuffer = nullptr; + gl::Error error = getStreamingIndexBuffer(dstType, &indexBuffer); + if (error.isError()) + { + return error; + } + ASSERT(indexBuffer != nullptr); + + unsigned int offset; + StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex, + &offset); + + translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->serial = indexBuffer->getSerial(); + translated->startIndex = (offset >> dstTypeInfo.bytesShift); + translated->startOffset = offset; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, + IndexBufferInterface **outBuffer) +{ + ASSERT(outBuffer); + if (destinationIndexType == GL_UNSIGNED_INT) + { + if (!mStreamingBufferInt) + { + mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory); + gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, + GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mStreamingBufferInt); + return error; + } + } + + *outBuffer = mStreamingBufferInt; + return gl::Error(GL_NO_ERROR); + } + else + { + ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); + + if (!mStreamingBufferShort) + { + mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory); + gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, + GL_UNSIGNED_SHORT); + if (error.isError()) + { + SafeDelete(mStreamingBufferShort); + return error; + } + } + + *outBuffer = mStreamingBufferShort; + return gl::Error(GL_NO_ERROR); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h new file mode 100755 index 000000000..44eb68c07 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 2002-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. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBANGLE_INDEXDATAMANAGER_H_ +#define LIBANGLE_INDEXDATAMANAGER_H_ + +#include <GLES2/gl2.h> + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ +class Buffer; +} + +namespace rx +{ +class IndexBufferInterface; +class StaticIndexBufferInterface; +class StreamingIndexBufferInterface; +class IndexBuffer; +class BufferD3D; +class RendererD3D; + +struct SourceIndexData +{ + BufferD3D *srcBuffer; + const GLvoid *srcIndices; + unsigned int srcCount; + GLenum srcIndexType; + bool srcIndicesChanged; +}; + +struct TranslatedIndexData +{ + gl::IndexRange indexRange; + unsigned int startIndex; + unsigned int startOffset; // In bytes + + IndexBuffer *indexBuffer; + BufferD3D *storage; + GLenum indexType; + unsigned int serial; + + SourceIndexData srcIndexData; +}; + +class IndexDataManager : angle::NonCopyable +{ + public: + explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); + virtual ~IndexDataManager(); + + gl::Error prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + bool primitiveRestartFixedIndexEnabled); + + private: + gl::Error streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated); + gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, + IndexBufferInterface **outBuffer); + + BufferFactoryD3D *const mFactory; + RendererClass mRendererClass; + StreamingIndexBufferInterface *mStreamingBufferShort; + StreamingIndexBufferInterface *mStreamingBufferInt; +}; + +} + +#endif // LIBANGLE_INDEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp new file mode 100755 index 000000000..113bad647 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindowD3D.cpp: Defines NativeWindowD3D, a class for managing and performing operations on +// an EGLNativeWindowType for the D3D renderers. + +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" + +namespace rx +{ + +NativeWindowD3D::NativeWindowD3D(EGLNativeWindowType window) : mWindow(window) +{ +} + +NativeWindowD3D::~NativeWindowD3D() +{ +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h new file mode 100755 index 000000000..365448488 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindowD3D.h: Defines NativeWindowD3D, a class for managing and performing operations on an +// EGLNativeWindowType for the D3D renderers. + +#ifndef LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_ +#define LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include <EGL/eglplatform.h> +#include "libANGLE/Config.h" + +namespace rx +{ +class NativeWindowD3D : angle::NonCopyable +{ + public: + NativeWindowD3D(EGLNativeWindowType window); + virtual ~NativeWindowD3D(); + + virtual bool initialize() = 0; + virtual bool getClientRect(LPRECT rect) const = 0; + virtual bool isIconic() const = 0; + + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + + private: + EGLNativeWindowType mWindow; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp new file mode 100755 index 000000000..d00a8738e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -0,0 +1,2301 @@ +// +// Copyright (c) 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. +// + +// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#include "libANGLE/renderer/d3d/ProgramD3D.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Uniform.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/VaryingPacking.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +namespace rx +{ + +namespace +{ + +gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) +{ + gl::InputLayout defaultLayout; + for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes()) + { + if (shaderAttr.type != GL_NONE) + { + GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); + + for (size_t rowIndex = 0; + static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex) + { + GLenum componentType = gl::VariableComponentType(transposedType); + GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType)); + bool pureInt = (componentType != GL_FLOAT); + gl::VertexFormatType defaultType = + gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt); + + defaultLayout.push_back(defaultType); + } + } + } + + return defaultLayout; +} + +std::vector<GLenum> GetDefaultOutputLayoutFromShader( + const std::vector<PixelShaderOutputVariable> &shaderOutputVars) +{ + std::vector<GLenum> defaultPixelOutput; + + if (!shaderOutputVars.empty()) + { + defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + + static_cast<unsigned int>(shaderOutputVars[0].outputIndex)); + } + + return defaultPixelOutput; +} + +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + +// true if varying x has a higher priority in packing than y +bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y) +{ + return gl::CompareShaderVar(*x.varying, *y.varying); +} + +std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, + const gl::Shader &fragmentShader, + const std::vector<std::string> &tfVaryings) +{ + std::vector<PackedVarying> packedVaryings; + + for (const sh::Varying &output : vertexShader.getVaryings()) + { + bool packed = false; + + // Built-in varyings obey special rules + if (output.isBuiltIn()) + { + continue; + } + + for (const sh::Varying &input : fragmentShader.getVaryings()) + { + if (output.name == input.name) + { + if (output.isStruct()) + { + ASSERT(!output.isArray()); + for (const auto &field : output.fields) + { + ASSERT(!field.isStruct() && !field.isArray()); + packedVaryings.push_back( + PackedVarying(field, input.interpolation, input.name)); + } + } + else + { + packedVaryings.push_back(PackedVarying(input, input.interpolation)); + } + packed = true; + break; + } + } + + // Keep Transform FB varyings in the merged list always. + if (!packed) + { + for (const std::string &tfVarying : tfVaryings) + { + if (tfVarying == output.name) + { + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (!output.isStruct()) + { + packedVaryings.push_back(PackedVarying(output, output.interpolation)); + packedVaryings.back().vertexOnly = true; + } + break; + } + } + } + } + + std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying); + + return packedVaryings; +} + +template <typename VarT> +void GetUniformBlockInfo(const std::vector<VarT> &fields, + const std::string &prefix, + sh::BlockLayoutEncoder *encoder, + bool inRowMajorLayout, + std::map<std::string, sh::BlockMemberInfo> *blockInfoOut) +{ + for (const VarT &field : fields) + { + const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); + + if (field.isStruct()) + { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + const std::string uniformElementName = + fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout, + blockInfoOut); + + encoder->exitAggregateType(); + } + } + else + { + bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); + (*blockInfoOut)[fieldName] = + encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); + } + } +} + +template <typename T> +static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); + + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template <typename T> +bool TransposeMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); + + for (int x = 0; x < copyWidth; x++) + { + for (int y = 0; y < copyHeight; y++) + { + SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) + { + for (int x = copyHeight; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + + return dirty; +} + +template <typename T> +bool ExpandMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetWidth, srcWidth); + int copyHeight = std::min(targetHeight, srcHeight); + + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyHeight; y++) + { + for (int x = copyWidth; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyHeight; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + + return dirty; +} + +gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode) +{ + switch (drawMode) + { + // Uses the point sprite geometry shader. + case GL_POINTS: + return gl::PRIMITIVE_POINTS; + + // All line drawing uses the same geometry shader. + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + return gl::PRIMITIVE_LINES; + + // The triangle fan primitive is emulated with strips in D3D11. + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + return gl::PRIMITIVE_TRIANGLES; + + // Special case for triangle strips. + case GL_TRIANGLE_STRIP: + return gl::PRIMITIVE_TRIANGLE_STRIP; + + default: + UNREACHABLE(); + return gl::PRIMITIVE_TYPE_MAX; + } +} + +} // anonymous namespace + +// D3DUniform Implementation + +D3DUniform::D3DUniform(GLenum typeIn, + const std::string &nameIn, + unsigned int arraySizeIn, + bool defaultBlock) + : type(typeIn), + name(nameIn), + arraySize(arraySizeIn), + data(nullptr), + dirty(true), + vsRegisterIndex(GL_INVALID_INDEX), + psRegisterIndex(GL_INVALID_INDEX), + registerCount(0), + registerElement(0) +{ + // We use data storage for default block uniforms to cache values that are sent to D3D during + // rendering + // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) + if (defaultBlock) + { + size_t bytes = gl::VariableInternalSize(type) * elementCount(); + data = new uint8_t[bytes]; + memset(data, 0, bytes); + + // TODO(jmadill): is this correct with non-square matrices? + registerCount = gl::VariableRowCount(type) * elementCount(); + } +} + +D3DUniform::~D3DUniform() +{ + SafeDeleteArray(data); +} + +bool D3DUniform::isSampler() const +{ + return gl::IsSamplerType(type); +} + +bool D3DUniform::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool D3DUniform::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + +// D3DVarying Implementation + +D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) +{ +} + +D3DVarying::D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn) + : semanticName(semanticNameIn), + semanticIndex(semanticIndexIn), + componentCount(componentCountIn), + outputSlot(outputSlotIn) +{ +} + +// ProgramD3DMetadata Implementation + +ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer, + const ShaderD3D *vertexShader, + const ShaderD3D *fragmentShader) + : mRendererMajorShaderModel(renderer->getMajorShaderModel()), + mShaderModelSuffix(renderer->getShaderModelSuffix()), + mUsesInstancedPointSpriteEmulation( + renderer->getWorkarounds().useInstancedPointSpriteEmulation), + mUsesViewScale(renderer->presentPathFastEnabled()), + mVertexShader(vertexShader), + mFragmentShader(fragmentShader) +{ +} + +int ProgramD3DMetadata::getRendererMajorShaderModel() const +{ + return mRendererMajorShaderModel; +} + +bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const +{ + return (mFragmentShader->usesFragColor() && data.getClientMajorVersion() < 3); +} + +bool ProgramD3DMetadata::usesFragDepth() const +{ + return mFragmentShader->usesFragDepth(); +} + +bool ProgramD3DMetadata::usesPointCoord() const +{ + return mFragmentShader->usesPointCoord(); +} + +bool ProgramD3DMetadata::usesFragCoord() const +{ + return mFragmentShader->usesFragCoord(); +} + +bool ProgramD3DMetadata::usesPointSize() const +{ + return mVertexShader->usesPointSize(); +} + +bool ProgramD3DMetadata::usesInsertedPointCoordValue() const +{ + return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() && + mRendererMajorShaderModel >= 4; +} + +bool ProgramD3DMetadata::usesViewScale() const +{ + return mUsesViewScale; +} + +bool ProgramD3DMetadata::addsPointCoordToVertexShader() const +{ + // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader + // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader. + // Even with a geometry shader, the app can render triangles or lines and reference + // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For + // simplicity, we always add this to the vertex shader when the fragment shader + // references gl_PointCoord, even if we could skip it in the geometry shader. + return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) || + usesInsertedPointCoordValue(); +} + +bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const +{ + // gl_Position only needs to be outputted from the vertex shader if transform feedback is + // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from + // the vertex shader in this case. This saves us 1 output vector. + return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != ""); +} + +bool ProgramD3DMetadata::usesSystemValuePointSize() const +{ + return !mUsesInstancedPointSpriteEmulation && usesPointSize(); +} + +bool ProgramD3DMetadata::usesMultipleFragmentOuts() const +{ + return mFragmentShader->usesMultipleRenderTargets(); +} + +GLint ProgramD3DMetadata::getMajorShaderVersion() const +{ + return mVertexShader->getData().getShaderVersion(); +} + +const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const +{ + return mFragmentShader; +} + +// ProgramD3D Implementation + +ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout, + const Signature &signature, + ShaderExecutableD3D *shaderExecutable) + : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable) +{ +} + +ProgramD3D::VertexExecutable::~VertexExecutable() +{ + SafeDelete(mShaderExecutable); +} + +// static +ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType( + GLenum type) +{ + switch (type) + { + case GL_INT: + return HLSLAttribType::SIGNED_INT; + case GL_UNSIGNED_INT: + return HLSLAttribType::UNSIGNED_INT; + case GL_SIGNED_NORMALIZED: + case GL_UNSIGNED_NORMALIZED: + case GL_FLOAT: + return HLSLAttribType::FLOAT; + default: + UNREACHABLE(); + return HLSLAttribType::FLOAT; + } +} + +// static +void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer, + const gl::InputLayout &inputLayout, + Signature *signatureOut) +{ + signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT); + + for (size_t index = 0; index < inputLayout.size(); ++index) + { + gl::VertexFormatType vertexFormatType = inputLayout[index]; + if (vertexFormatType == gl::VERTEX_FORMAT_INVALID) + continue; + + VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType); + if ((conversionType & VERTEX_CONVERT_GPU) == 0) + continue; + + GLenum componentType = renderer->getVertexComponentType(vertexFormatType); + (*signatureOut)[index] = GetAttribType(componentType); + } +} + +bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const +{ + size_t limit = std::max(mSignature.size(), signature.size()); + for (size_t index = 0; index < limit; ++index) + { + // treat undefined indexes as FLOAT + auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT; + auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT; + if (a != b) + return false; + } + + return true; +} + +ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, + ShaderExecutableD3D *shaderExecutable) + : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable) +{ +} + +ProgramD3D::PixelExecutable::~PixelExecutable() +{ + SafeDelete(mShaderExecutable); +} + +ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) +{ +} + +unsigned int ProgramD3D::mCurrentSerial = 1; + +ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer) + : ProgramImpl(state), + mRenderer(renderer), + mDynamicHLSL(NULL), + mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr), + mUsesPointSize(false), + mUsesFlatInterpolation(false), + mVertexUniformStorage(NULL), + mFragmentUniformStorage(NULL), + mUsedVertexSamplerRange(0), + mUsedPixelSamplerRange(0), + mDirtySamplerMapping(true), + mSerial(issueSerial()) +{ + mDynamicHLSL = new DynamicHLSL(renderer); +} + +ProgramD3D::~ProgramD3D() +{ + reset(); + SafeDelete(mDynamicHLSL); +} + +bool ProgramD3D::usesPointSpriteEmulation() const +{ + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; +} + +bool ProgramD3D::usesGeometryShader(GLenum drawMode) const +{ + if (drawMode != GL_POINTS) + { + return mUsesFlatInterpolation; + } + + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); +} + +bool ProgramD3D::usesInstancedPointSpriteEmulation() const +{ + return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; +} + +GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, + unsigned int samplerIndex, + const gl::Caps &caps) const +{ + GLint logicalTextureUnit = -1; + + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: + UNREACHABLE(); + } + + if (logicalTextureUnit >= 0 && + logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) + { + return logicalTextureUnit; + } + + return -1; +} + +// Returns the texture type for a given Direct3D 9 sampler type and +// index (0-15 for the pixel shader and 0-3 for the vertex shader). +GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < mSamplersPS.size()); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < mSamplersVS.size()); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: + UNREACHABLE(); + } + + return GL_TEXTURE_2D; +} + +GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + return mUsedPixelSamplerRange; + case gl::SAMPLER_VERTEX: + return mUsedVertexSamplerRange; + default: + UNREACHABLE(); + return 0u; + } +} + +void ProgramD3D::updateSamplerMapping() +{ + if (!mDirtySamplerMapping) + { + return; + } + + mDirtySamplerMapping = false; + + // Retrieve sampler uniform values + for (const D3DUniform *d3dUniform : mD3DUniforms) + { + if (!d3dUniform->dirty) + continue; + + if (!d3dUniform->isSampler()) + continue; + + int count = d3dUniform->elementCount(); + const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data); + + if (d3dUniform->isReferencedByFragmentShader()) + { + unsigned int firstIndex = d3dUniform->psRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersPS.size()) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + + if (d3dUniform->isReferencedByVertexShader()) + { + unsigned int firstIndex = d3dUniform->vsRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersVS.size()) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + } +} + +LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + reset(); + + DeviceIdentifier binaryDeviceIdentifier = {0}; + stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier), + sizeof(DeviceIdentifier)); + + DeviceIdentifier identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0) + { + infoLog << "Invalid program binary, device configuration has changed."; + return false; + } + + int compileFlags = stream->readInt<int>(); + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) + { + infoLog << "Mismatched compilation flags."; + return false; + } + + for (int &index : mAttribLocationToD3DSemantic) + { + stream->readInt(&index); + } + + const unsigned int psSamplerCount = stream->readInt<unsigned int>(); + for (unsigned int i = 0; i < psSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); + } + const unsigned int vsSamplerCount = stream->readInt<unsigned int>(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); + } + + stream->readInt(&mUsedVertexSamplerRange); + stream->readInt(&mUsedPixelSamplerRange); + + const unsigned int uniformCount = stream->readInt<unsigned int>(); + if (stream->error()) + { + infoLog << "Invalid program binary."; + return false; + } + + const auto &linkedUniforms = mState.getUniforms(); + ASSERT(mD3DUniforms.empty()); + for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) + { + const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex]; + + D3DUniform *d3dUniform = + new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize, + linkedUniform.isInDefaultBlock()); + stream->readInt(&d3dUniform->psRegisterIndex); + stream->readInt(&d3dUniform->vsRegisterIndex); + stream->readInt(&d3dUniform->registerCount); + stream->readInt(&d3dUniform->registerElement); + + mD3DUniforms.push_back(d3dUniform); + } + + const unsigned int blockCount = stream->readInt<unsigned int>(); + if (stream->error()) + { + infoLog << "Invalid program binary."; + return false; + } + + ASSERT(mD3DUniformBlocks.empty()); + for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + D3DUniformBlock uniformBlock; + stream->readInt(&uniformBlock.psRegisterIndex); + stream->readInt(&uniformBlock.vsRegisterIndex); + mD3DUniformBlocks.push_back(uniformBlock); + } + + const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>(); + mStreamOutVaryings.resize(streamOutVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex) + { + D3DVarying *varying = &mStreamOutVaryings[varyingIndex]; + + stream->readString(&varying->semanticName); + stream->readInt(&varying->semanticIndex); + stream->readInt(&varying->componentCount); + stream->readInt(&varying->outputSlot); + } + + stream->readString(&mVertexHLSL); + stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); + stream->readString(&mPixelHLSL); + stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); + stream->readBool(&mUsesFragDepth); + stream->readBool(&mUsesPointSize); + stream->readBool(&mUsesFlatInterpolation); + + const size_t pixelShaderKeySize = stream->readInt<unsigned int>(); + mPixelShaderKey.resize(pixelShaderKeySize); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; + pixelShaderKeyIndex++) + { + stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); + stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); + stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source); + stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); + } + + stream->readString(&mGeometryShaderPreamble); + + const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data()); + + bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS); + + const unsigned int vertexShaderCount = stream->readInt<unsigned int>(); + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; + vertexShaderIndex++) + { + size_t inputLayoutSize = stream->readInt<size_t>(); + gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID); + + for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++) + { + inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>(); + } + + unsigned int vertexShaderSize = stream->readInt<unsigned int>(); + const unsigned char *vertexShaderFunction = binary + stream->offset(); + + ShaderExecutableD3D *shaderExecutable = nullptr; + + ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, + mStreamOutVaryings, separateAttribs, + &shaderExecutable)); + + if (!shaderExecutable) + { + infoLog << "Could not create vertex shader."; + return false; + } + + // generated converted input layout + VertexExecutable::Signature signature; + VertexExecutable::getSignature(mRenderer, inputLayout, &signature); + + // add new binary + mVertexExecutables.push_back( + new VertexExecutable(inputLayout, signature, shaderExecutable)); + + stream->skip(vertexShaderSize); + } + + const size_t pixelShaderCount = stream->readInt<unsigned int>(); + for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) + { + const size_t outputCount = stream->readInt<unsigned int>(); + std::vector<GLenum> outputs(outputCount); + for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) + { + stream->readInt(&outputs[outputIndex]); + } + + const size_t pixelShaderSize = stream->readInt<unsigned int>(); + const unsigned char *pixelShaderFunction = binary + stream->offset(); + ShaderExecutableD3D *shaderExecutable = nullptr; + + ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, + mStreamOutVaryings, separateAttribs, + &shaderExecutable)); + + if (!shaderExecutable) + { + infoLog << "Could not create pixel shader."; + return false; + } + + // add new binary + mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); + + stream->skip(pixelShaderSize); + } + + for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX; + ++geometryExeIndex) + { + unsigned int geometryShaderSize = stream->readInt<unsigned int>(); + if (geometryShaderSize == 0) + { + mGeometryExecutables[geometryExeIndex] = nullptr; + continue; + } + + const unsigned char *geometryShaderFunction = binary + stream->offset(); + + ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, + SHADER_GEOMETRY, mStreamOutVaryings, separateAttribs, + &mGeometryExecutables[geometryExeIndex])); + + if (!mGeometryExecutables[geometryExeIndex]) + { + infoLog << "Could not create geometry shader."; + return false; + } + stream->skip(geometryShaderSize); + } + + initializeUniformStorage(); + + return true; +} + +gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) +{ + // Output the DeviceIdentifier before we output any shader code + // When we load the binary again later, we can validate the device identifier before trying to + // compile any HLSL + DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier(); + stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier), + sizeof(DeviceIdentifier)); + + stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); + + for (int d3dSemantic : mAttribLocationToD3DSemantic) + { + stream->writeInt(d3dSemantic); + } + + stream->writeInt(mSamplersPS.size()); + for (unsigned int i = 0; i < mSamplersPS.size(); ++i) + { + stream->writeInt(mSamplersPS[i].active); + stream->writeInt(mSamplersPS[i].logicalTextureUnit); + stream->writeInt(mSamplersPS[i].textureType); + } + + stream->writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) + { + stream->writeInt(mSamplersVS[i].active); + stream->writeInt(mSamplersVS[i].logicalTextureUnit); + stream->writeInt(mSamplersVS[i].textureType); + } + + stream->writeInt(mUsedVertexSamplerRange); + stream->writeInt(mUsedPixelSamplerRange); + + stream->writeInt(mD3DUniforms.size()); + for (const D3DUniform *uniform : mD3DUniforms) + { + // Type, name and arraySize are redundant, so aren't stored in the binary. + stream->writeIntOrNegOne(uniform->psRegisterIndex); + stream->writeIntOrNegOne(uniform->vsRegisterIndex); + stream->writeInt(uniform->registerCount); + stream->writeInt(uniform->registerElement); + } + + stream->writeInt(mD3DUniformBlocks.size()); + for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks) + { + stream->writeIntOrNegOne(uniformBlock.psRegisterIndex); + stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex); + } + + stream->writeInt(mStreamOutVaryings.size()); + for (const auto &varying : mStreamOutVaryings) + { + stream->writeString(varying.semanticName); + stream->writeInt(varying.semanticIndex); + stream->writeInt(varying.componentCount); + stream->writeInt(varying.outputSlot); + } + + stream->writeString(mVertexHLSL); + stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); + stream->writeString(mPixelHLSL); + stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); + stream->writeInt(mUsesFragDepth); + stream->writeInt(mUsesPointSize); + stream->writeInt(mUsesFlatInterpolation); + + const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey; + stream->writeInt(pixelShaderKey.size()); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); + pixelShaderKeyIndex++) + { + const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; + stream->writeInt(variable.type); + stream->writeString(variable.name); + stream->writeString(variable.source); + stream->writeInt(variable.outputIndex); + } + + stream->writeString(mGeometryShaderPreamble); + + stream->writeInt(mVertexExecutables.size()); + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); + vertexExecutableIndex++) + { + VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; + + const auto &inputLayout = vertexExecutable->inputs(); + stream->writeInt(inputLayout.size()); + + for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++) + { + stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex])); + } + + size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); + stream->writeInt(vertexShaderSize); + + const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(vertexBlob, vertexShaderSize); + } + + stream->writeInt(mPixelExecutables.size()); + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); + pixelExecutableIndex++) + { + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + + const std::vector<GLenum> outputs = pixelExecutable->outputSignature(); + stream->writeInt(outputs.size()); + for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) + { + stream->writeInt(outputs[outputIndex]); + } + + size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); + stream->writeInt(pixelShaderSize); + + const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(pixelBlob, pixelShaderSize); + } + + for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables) + { + if (geometryExe == nullptr) + { + stream->writeInt(0); + continue; + } + + size_t geometryShaderSize = geometryExe->getLength(); + stream->writeInt(geometryShaderSize); + stream->writeBytes(geometryExe->getFunction(), geometryShaderSize); + } + + return gl::Error(GL_NO_ERROR); +} + +void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) +{ +} + +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExecutable) +{ + mPixelShaderOutputFormatCache.clear(); + + const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo); + const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) + { + mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK + ? GL_COLOR_ATTACHMENT0 + : colorbuffer->getBinding()); + } + else + { + mPixelShaderOutputFormatCache.push_back(GL_NONE); + } + } + + return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr); +} + +gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) +{ + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) + { + *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature( + mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature); + + // Generate new pixel executable + ShaderExecutableD3D *pixelExecutable = NULL; + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, + &pixelExecutable); + if (error.isError()) + { + return error; + } + + if (pixelExecutable) + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + else if (!infoLog) + { + std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); + } + + *outExectuable = pixelExecutable; + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) +{ + VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature); + + for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + { + if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature)) + { + *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + + // Generate new dynamic layout with attribute conversions + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout( + mVertexHLSL, inputLayout, mState.getAttributes()); + + // Generate new vertex executable + ShaderExecutableD3D *vertexExecutable = NULL; + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, + &vertexExecutable); + if (error.isError()) + { + return error; + } + + if (vertexExecutable) + { + mVertexExecutables.push_back( + new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)); + } + else if (!infoLog) + { + std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); + } + + *outExectuable = vertexExecutable; + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextState &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog) +{ + if (outExecutable) + { + *outExecutable = nullptr; + } + + // Return a null shader if the current rendering doesn't use a geometry shader + if (!usesGeometryShader(drawMode)) + { + return gl::Error(GL_NO_ERROR); + } + + gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode); + + if (mGeometryExecutables[geometryShaderType] != nullptr) + { + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return gl::Error(GL_NO_ERROR); + } + + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL( + geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(), + mGeometryShaderPreamble); + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(), + &mGeometryExecutables[geometryShaderType]); + + if (!infoLog && error.isError()) + { + std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]); + } + + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return error; +} + +LinkResult ProgramD3D::compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog) +{ + const gl::InputLayout &defaultInputLayout = + GetDefaultInputLayoutFromShader(mState.getAttachedVertexShader()); + ShaderExecutableD3D *defaultVertexExecutable = nullptr; + ANGLE_TRY( + getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog)); + + std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); + ShaderExecutableD3D *defaultPixelExecutable = nullptr; + ANGLE_TRY( + getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog)); + + // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11. + ShaderExecutableD3D *pointGS = nullptr; + if (usesGeometryShader(GL_POINTS)) + { + getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog); + } + + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); + + if (usesGeometryShader(GL_POINTS) && pointGS) + { + // Geometry shaders are currently only used internally, so there is no corresponding shader + // object at the interface level. For now the geometry shader debug info is prepended to + // the vertex shader. + vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); + vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo()); + vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); + } + + if (defaultVertexExecutable) + { + vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo()); + } + + if (defaultPixelExecutable) + { + const ShaderD3D *fragmentShaderD3D = + GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); + fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); + } + + return (defaultVertexExecutable && defaultPixelExecutable && + (!usesGeometryShader(GL_POINTS) || pointGS)); +} + +LinkResult ProgramD3D::link(const gl::ContextState &data, gl::InfoLog &infoLog) +{ + reset(); + + const gl::Shader *vertexShader = mState.getAttachedVertexShader(); + const gl::Shader *fragmentShader = mState.getAttachedFragmentShader(); + + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader); + const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader); + + mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits); + mSamplersPS.resize(data.getCaps().maxTextureImageUnits); + + vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); + fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); + + if (mRenderer->getNativeLimitations().noFrontFacingSupport) + { + if (fragmentShaderD3D->usesFrontFacing()) + { + infoLog << "The current renderer doesn't support gl_FrontFacing"; + return false; + } + } + + std::vector<PackedVarying> packedVaryings = + MergeVaryings(*vertexShader, *fragmentShader, mState.getTransformFeedbackVaryingNames()); + + // Map the varyings to the register file + VaryingPacking varyingPacking(data.getCaps().maxVaryingVectors); + if (!varyingPacking.packVaryings(infoLog, packedVaryings, + mState.getTransformFeedbackVaryingNames())) + { + return false; + } + + ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D); + + varyingPacking.enableBuiltins(SHADER_VERTEX, metadata); + varyingPacking.enableBuiltins(SHADER_PIXEL, metadata); + + if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.getCaps().maxVaryingVectors) + { + infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord"; + return false; + } + + // TODO(jmadill): Implement more sophisticated component packing in D3D9. + // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings + // intelligently, but D3D9 assumes one semantic per register. + if (mRenderer->getRendererClass() == RENDERER_D3D9 && + varyingPacking.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors) + { + infoLog << "Cannot pack these varyings on D3D9."; + return false; + } + + if (!mDynamicHLSL->generateShaderLinkHLSL(data, mState, metadata, varyingPacking, &mPixelHLSL, + &mVertexHLSL)) + { + return false; + } + + mUsesPointSize = vertexShaderD3D->usesPointSize(); + mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey); + mUsesFragDepth = metadata.usesFragDepth(); + + // Cache if we use flat shading + mUsesFlatInterpolation = false; + for (const auto &varying : packedVaryings) + { + if (varying.interpolation == sh::INTERPOLATION_FLAT) + { + mUsesFlatInterpolation = true; + break; + } + } + + if (mRenderer->getMajorShaderModel() >= 4) + { + varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata); + mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking); + } + + initAttribLocationsToD3DSemantic(); + + defineUniformsAndAssignRegisters(); + + gatherTransformFeedbackVaryings(varyingPacking); + + LinkResult result = compileProgramExecutables(data, infoLog); + if (result.isError()) + { + infoLog << result.getError().getMessage(); + return result; + } + else if (!result.getResult()) + { + infoLog << "Failed to create D3D shaders."; + return result; + } + + initUniformBlockInfo(); + + return true; +} + +GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/) +{ + // TODO(jmadill): Do something useful here? + return GL_TRUE; +} + +void ProgramD3D::initUniformBlockInfo() +{ + const gl::Shader *vertexShader = mState.getAttachedVertexShader(); + + for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks()) + { + if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (mBlockDataSizes.count(vertexBlock.name) > 0) + continue; + + size_t dataSize = getUniformBlockInfo(vertexBlock); + mBlockDataSizes[vertexBlock.name] = dataSize; + } + + const gl::Shader *fragmentShader = mState.getAttachedFragmentShader(); + + for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks()) + { + if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (mBlockDataSizes.count(fragmentBlock.name) > 0) + continue; + + size_t dataSize = getUniformBlockInfo(fragmentBlock); + mBlockDataSizes[fragmentBlock.name] = dataSize; + } +} + +void ProgramD3D::assignUniformBlockRegisters() +{ + mD3DUniformBlocks.clear(); + + // Assign registers and update sizes. + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); + + for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks()) + { + unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0; + + D3DUniformBlock d3dUniformBlock; + + if (uniformBlock.vertexStaticUse) + { + unsigned int baseRegister = + vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement; + } + + if (uniformBlock.fragmentStaticUse) + { + unsigned int baseRegister = + fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement; + } + + mD3DUniformBlocks.push_back(d3dUniformBlock); + } +} + +void ProgramD3D::initializeUniformStorage() +{ + // Compute total default block size + unsigned int vertexRegisters = 0; + unsigned int fragmentRegisters = 0; + for (const D3DUniform *d3dUniform : mD3DUniforms) + { + if (!d3dUniform->isSampler()) + { + if (d3dUniform->isReferencedByVertexShader()) + { + vertexRegisters = std::max(vertexRegisters, + d3dUniform->vsRegisterIndex + d3dUniform->registerCount); + } + if (d3dUniform->isReferencedByFragmentShader()) + { + fragmentRegisters = std::max( + fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount); + } + } + } + + mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); + mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); +} + +gl::Error ProgramD3D::applyUniforms(GLenum drawMode) +{ + ASSERT(!mDirtySamplerMapping); + + gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms); + if (error.isError()) + { + return error; + } + + for (D3DUniform *d3dUniform : mD3DUniforms) + { + d3dUniform->dirty = false; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::applyUniformBuffers(const gl::ContextState &data) +{ + if (mState.getUniformBlocks().empty()) + { + return gl::Error(GL_NO_ERROR); + } + + // Lazy init. + if (mD3DUniformBlocks.empty()) + { + assignUniformBlockRegisters(); + } + + mVertexUBOCache.clear(); + mFragmentUBOCache.clear(); + + const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); + + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size(); + uniformBlockIndex++) + { + const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex]; + GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex); + + // Unnecessary to apply an unreferenced standard or shared UBO + if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse()) + { + continue; + } + + if (uniformBlock.vertexStaticUse()) + { + unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS; + ASSERT(registerIndex < data.getCaps().maxVertexUniformBlocks); + + if (mVertexUBOCache.size() <= registerIndex) + { + mVertexUBOCache.resize(registerIndex + 1, -1); + } + + ASSERT(mVertexUBOCache[registerIndex] == -1); + mVertexUBOCache[registerIndex] = blockBinding; + } + + if (uniformBlock.fragmentStaticUse()) + { + unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS; + ASSERT(registerIndex < data.getCaps().maxFragmentUniformBlocks); + + if (mFragmentUBOCache.size() <= registerIndex) + { + mFragmentUBOCache.resize(registerIndex + 1, -1); + } + + ASSERT(mFragmentUBOCache[registerIndex] == -1); + mFragmentUBOCache[registerIndex] = blockBinding; + } + } + + return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache); +} + +void ProgramD3D::dirtyAllUniforms() +{ + for (D3DUniform *d3dUniform : mD3DUniforms) + { + d3dUniform->dirty = true; + } +} + +void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT); +} + +void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC2); +} + +void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC3); +} + +void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC4); +} + +void ProgramD3D::setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); +} + +void ProgramD3D::setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); +} + +void ProgramD3D::setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +} + +void ProgramD3D::setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +} + +void ProgramD3D::setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +} + +void ProgramD3D::setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +} + +void ProgramD3D::setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +} + +void ProgramD3D::setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); +} + +void ProgramD3D::setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) +{ + setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +} + +void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT); +} + +void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC2); +} + +void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC3); +} + +void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC4); +} + +void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT); +} + +void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); +} + +void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); +} + +void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); +} + +void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, + GLuint /*uniformBlockBinding*/) +{ +} + +void ProgramD3D::defineUniformsAndAssignRegisters() +{ + D3DUniformMap uniformMap; + const gl::Shader *vertexShader = mState.getAttachedVertexShader(); + for (const sh::Uniform &vertexUniform : vertexShader->getUniforms()) + + { + if (vertexUniform.staticUse) + { + defineUniformBase(vertexShader, vertexUniform, &uniformMap); + } + } + + const gl::Shader *fragmentShader = mState.getAttachedFragmentShader(); + for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms()) + { + if (fragmentUniform.staticUse) + { + defineUniformBase(fragmentShader, fragmentUniform, &uniformMap); + } + } + + // Initialize the D3DUniform list to mirror the indexing of the GL layer. + for (const gl::LinkedUniform &glUniform : mState.getUniforms()) + { + if (!glUniform.isInDefaultBlock()) + continue; + + auto mapEntry = uniformMap.find(glUniform.name); + ASSERT(mapEntry != uniformMap.end()); + mD3DUniforms.push_back(mapEntry->second); + } + + assignAllSamplerRegisters(); + initializeUniformStorage(); +} + +void ProgramD3D::defineUniformBase(const gl::Shader *shader, + const sh::Uniform &uniform, + D3DUniformMap *uniformMap) +{ + // Samplers get their registers assigned in assignAllSamplerRegisters. + if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type)) + { + defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap); + return; + } + + const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader); + + unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name); + ShShaderOutput outputType = shaderD3D->getCompilerOutputType(); + sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); + encoder.skipRegisters(startRegister); + + defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap); +} + +D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name) +{ + for (D3DUniform *d3dUniform : mD3DUniforms) + { + if (d3dUniform->name == name) + { + return d3dUniform; + } + } + + return nullptr; +} + +void ProgramD3D::defineUniform(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap) +{ + if (uniform.isStruct()) + { + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + { + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); + + if (encoder) + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); + + // Samplers get their registers assigned in assignAllSamplerRegisters. + // Also they couldn't use the same encoder as the rest of the struct, since they are + // extracted out of the struct by the shader translator. + if (gl::IsSamplerType(field.type)) + { + defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap); + } + else + { + defineUniform(shaderType, field, fieldFullName, encoder, uniformMap); + } + } + + if (encoder) + encoder->exitAggregateType(); + } + return; + } + + // Not a struct. Arrays are treated as aggregate types. + if (uniform.isArray() && encoder) + { + encoder->enterAggregateType(); + } + + // Advance the uniform offset, to track registers allocation for structs + sh::BlockMemberInfo blockInfo = + encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false) + : sh::BlockMemberInfo::getDefaultBlockInfo(); + + auto uniformMapEntry = uniformMap->find(fullName); + D3DUniform *d3dUniform = nullptr; + + if (uniformMapEntry != uniformMap->end()) + { + d3dUniform = uniformMapEntry->second; + } + else + { + d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true); + (*uniformMap)[fullName] = d3dUniform; + } + + if (encoder) + { + d3dUniform->registerElement = + static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo)); + unsigned int reg = + static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo)); + if (shaderType == GL_FRAGMENT_SHADER) + { + d3dUniform->psRegisterIndex = reg; + } + else + { + ASSERT(shaderType == GL_VERTEX_SHADER); + d3dUniform->vsRegisterIndex = reg; + } + + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->exitAggregateType(); + } + } +} + +template <typename T> +void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType) +{ + const int components = gl::VariableComponentCount(targetUniformType); + const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); + + D3DUniform *targetUniform = getD3DUniformFromLocation(location); + + unsigned int elementCount = targetUniform->elementCount(); + unsigned int arrayElement = mState.getUniformLocations()[location].element; + unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn)); + + if (targetUniform->type == targetUniformType) + { + T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4; + + for (unsigned int i = 0; i < count; i++) + { + T *dest = target + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, source[c], &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, T(0), &targetUniform->dirty); + } + } + } + else if (targetUniform->type == targetBoolType) + { + GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4; + + for (unsigned int i = 0; i < count; i++) + { + GLint *dest = boolParams + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, + &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); + } + } + } + else if (targetUniform->isSampler()) + { + ASSERT(targetUniformType == GL_INT); + + GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4; + + bool wasDirty = targetUniform->dirty; + + for (unsigned int i = 0; i < count; i++) + { + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components); + + SetIfDirty(dest + 0, source[0], &targetUniform->dirty); + SetIfDirty(dest + 1, 0, &targetUniform->dirty); + SetIfDirty(dest + 2, 0, &targetUniform->dirty); + SetIfDirty(dest + 3, 0, &targetUniform->dirty); + } + + if (!wasDirty && targetUniform->dirty) + { + mDirtySamplerMapping = true; + } + } + else + UNREACHABLE(); +} + +template <int cols, int rows> +void ProgramD3D::setUniformMatrixfv(GLint location, + GLsizei countIn, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType) +{ + D3DUniform *targetUniform = getD3DUniformFromLocation(location); + + unsigned int elementCount = targetUniform->elementCount(); + unsigned int arrayElement = mState.getUniformLocations()[location].element; + unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn)); + + const unsigned int targetMatrixStride = (4 * rows); + GLfloat *target = + (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride); + + for (unsigned int i = 0; i < count; i++) + { + // Internally store matrices as transposed versions to accomodate HLSL matrix indexing + if (transpose == GL_FALSE) + { + targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || + targetUniform->dirty; + } + else + { + targetUniform->dirty = + ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty; + } + target += targetMatrixStride; + value += cols * rows; + } +} + +size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock) +{ + ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED); + + // define member uniforms + sh::Std140BlockEncoder std140Encoder; + sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + sh::BlockLayoutEncoder *encoder = nullptr; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + { + encoder = &std140Encoder; + } + else + { + encoder = &hlslEncoder; + } + + GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, + interfaceBlock.isRowMajorLayout, &mBlockInfo); + + return encoder->getBlockSize(); +} + +void ProgramD3D::assignAllSamplerRegisters() +{ + for (D3DUniform *d3dUniform : mD3DUniforms) + { + if (d3dUniform->isSampler()) + { + assignSamplerRegisters(d3dUniform); + } + } +} + +void ProgramD3D::assignSamplerRegisters(D3DUniform *d3dUniform) +{ + ASSERT(d3dUniform->isSampler()); + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); + ASSERT(vertexShaderD3D->hasUniform(d3dUniform) || fragmentShaderD3D->hasUniform(d3dUniform)); + if (vertexShaderD3D->hasUniform(d3dUniform)) + { + d3dUniform->vsRegisterIndex = vertexShaderD3D->getUniformRegister(d3dUniform->name); + ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX); + AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize, + mSamplersVS, &mUsedVertexSamplerRange); + } + if (fragmentShaderD3D->hasUniform(d3dUniform)) + { + d3dUniform->psRegisterIndex = fragmentShaderD3D->getUniformRegister(d3dUniform->name); + ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX); + AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize, + mSamplersPS, &mUsedPixelSamplerRange); + } +} + +// static +void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector<Sampler> &outSamplers, + GLuint *outUsedRange) +{ + unsigned int samplerIndex = startSamplerIndex; + + do + { + ASSERT(samplerIndex < outSamplers.size()); + Sampler *sampler = &outSamplers[samplerIndex]; + sampler->active = true; + sampler->textureType = gl::SamplerTypeToTextureType(samplerType); + sampler->logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); + samplerIndex++; + } while (samplerIndex < startSamplerIndex + samplerCount); +} + +void ProgramD3D::reset() +{ + SafeDeleteContainer(mVertexExecutables); + SafeDeleteContainer(mPixelExecutables); + + for (auto &element : mGeometryExecutables) + { + SafeDelete(element); + } + + mVertexHLSL.clear(); + mVertexWorkarounds = D3DCompilerWorkarounds(); + + mPixelHLSL.clear(); + mPixelWorkarounds = D3DCompilerWorkarounds(); + mUsesFragDepth = false; + mPixelShaderKey.clear(); + mUsesPointSize = false; + mUsesFlatInterpolation = false; + + SafeDeleteContainer(mD3DUniforms); + mD3DUniformBlocks.clear(); + + SafeDelete(mVertexUniformStorage); + SafeDelete(mFragmentUniformStorage); + + mSamplersPS.clear(); + mSamplersVS.clear(); + + mUsedVertexSamplerRange = 0; + mUsedPixelSamplerRange = 0; + mDirtySamplerMapping = true; + + mAttribLocationToD3DSemantic.fill(-1); + + mStreamOutVaryings.clear(); + + mGeometryShaderPreamble.clear(); +} + +unsigned int ProgramD3D::getSerial() const +{ + return mSerial; +} + +unsigned int ProgramD3D::issueSerial() +{ + return mCurrentSerial++; +} + +void ProgramD3D::initAttribLocationsToD3DSemantic() +{ + const gl::Shader *vertexShader = mState.getAttachedVertexShader(); + ASSERT(vertexShader != nullptr); + + // Init semantic index + for (const sh::Attribute &attribute : mState.getAttributes()) + { + int d3dSemantic = vertexShader->getSemanticIndex(attribute.name); + int regCount = gl::VariableRegisterCount(attribute.type); + + for (int reg = 0; reg < regCount; ++reg) + { + mAttribLocationToD3DSemantic[attribute.location + reg] = d3dSemantic + reg; + } + } +} + +void ProgramD3D::updateCachedInputLayout(const gl::State &state) +{ + mCachedInputLayout.clear(); + const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + + for (unsigned int locationIndex : angle::IterateBitSet(mState.getActiveAttribLocationsMask())) + { + int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex]; + + if (d3dSemantic != -1) + { + if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1)) + { + mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID); + } + mCachedInputLayout[d3dSemantic] = + GetVertexFormatType(vertexAttributes[locationIndex], + state.getVertexAttribCurrentValue(locationIndex).Type); + } + } +} + +void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking) +{ + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + + const std::string &varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize()); + + // Gather the linked varyings that are used for transform feedback, they should all exist. + mStreamOutVaryings.clear(); + + const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames(); + for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size()); + ++outputSlot) + { + const auto &tfVaryingName = tfVaryingNames[outputSlot]; + if (tfVaryingName == "gl_Position") + { + if (builtins.glPosition.enabled) + { + mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic, + builtins.glPosition.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_FragCoord") + { + if (builtins.glFragCoord.enabled) + { + mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic, + builtins.glFragCoord.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_PointSize") + { + if (builtins.glPointSize.enabled) + { + mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot)); + } + } + else + { + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &varying = *registerInfo.packedVarying->varying; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + int componentCount = gl::VariableColumnCount(transposedType); + ASSERT(!varying.isBuiltIn()); + + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (registerInfo.packedVarying->isStructField() || varying.isStruct()) + continue; + + // There can be more than one register assigned to a particular varying, and each + // register needs its own stream out entry. + if (tfVaryingName == varying.name) + { + mStreamOutVaryings.push_back(D3DVarying( + varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot)); + } + } + } + } +} + +D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) +{ + return mD3DUniforms[mState.getUniformLocations()[location].index]; +} + +bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const +{ + std::string baseName = blockName; + gl::ParseAndStripArrayIndex(&baseName); + + auto sizeIter = mBlockDataSizes.find(baseName); + if (sizeIter == mBlockDataSizes.end()) + { + *sizeOut = 0; + return false; + } + + *sizeOut = sizeIter->second; + return true; +} + +bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const +{ + auto infoIter = mBlockInfo.find(memberUniformName); + if (infoIter == mBlockInfo.end()) + { + *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; + } + + *memberInfoOut = infoIter->second; + return true; +} + +void ProgramD3D::setPathFragmentInputGen(const std::string &inputName, + GLenum genMode, + GLint components, + const GLfloat *coeffs) +{ + UNREACHABLE(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h new file mode 100755 index 000000000..88fe4020d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -0,0 +1,414 @@ +// +// Copyright (c) 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. +// + +// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ + +#include <string> +#include <vector> + +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/Constants.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ProgramImpl.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" + +namespace rx +{ +class RendererD3D; +class UniformStorageD3D; +class ShaderExecutableD3D; + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. +// It should only be used selectively to work around specific bugs. +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 +#endif + +// Helper struct representing a single shader uniform +struct D3DUniform : angle::NonCopyable +{ + D3DUniform(GLenum typeIn, + const std::string &nameIn, + unsigned int arraySizeIn, + bool defaultBlock); + ~D3DUniform(); + + bool isSampler() const; + unsigned int elementCount() const { return std::max(1u, arraySize); } + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + + // Duplicated from the GL layer + GLenum type; + std::string name; + unsigned int arraySize; + + // Pointer to a system copy of the data. + // TODO(jmadill): remove this in favor of gl::LinkedUniform::data(). + uint8_t *data; + + // Has the data been updated since the last sync? + bool dirty; + + // Register information. + unsigned int vsRegisterIndex; + unsigned int psRegisterIndex; + unsigned int registerCount; + + // Register "elements" are used for uniform structs in ES3, to appropriately identify single + // uniforms + // inside aggregate types, which are packed according C-like structure rules. + unsigned int registerElement; +}; + +struct D3DUniformBlock +{ + D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {} + + bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } + + bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } + + unsigned int vsRegisterIndex; + unsigned int psRegisterIndex; +}; + +struct D3DVarying final +{ + D3DVarying(); + D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn); + + D3DVarying(const D3DVarying &) = default; + D3DVarying &operator=(const D3DVarying &) = default; + + std::string semanticName; + unsigned int semanticIndex; + unsigned int componentCount; + unsigned int outputSlot; +}; + +class ProgramD3DMetadata final : angle::NonCopyable +{ + public: + ProgramD3DMetadata(RendererD3D *renderer, + const ShaderD3D *vertexShader, + const ShaderD3D *fragmentShader); + + int getRendererMajorShaderModel() const; + bool usesBroadcast(const gl::ContextState &data) const; + bool usesFragDepth() const; + bool usesPointCoord() const; + bool usesFragCoord() const; + bool usesPointSize() const; + bool usesInsertedPointCoordValue() const; + bool usesViewScale() const; + bool addsPointCoordToVertexShader() const; + bool usesTransformFeedbackGLPosition() const; + bool usesSystemValuePointSize() const; + bool usesMultipleFragmentOuts() const; + GLint getMajorShaderVersion() const; + const ShaderD3D *getFragmentShader() const; + + private: + const int mRendererMajorShaderModel; + const std::string mShaderModelSuffix; + const bool mUsesInstancedPointSpriteEmulation; + const bool mUsesViewScale; + const ShaderD3D *mVertexShader; + const ShaderD3D *mFragmentShader; +}; + +class ProgramD3D : public ProgramImpl +{ + public: + ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer); + virtual ~ProgramD3D(); + + const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } + + GLint getSamplerMapping(gl::SamplerType type, + unsigned int samplerIndex, + const gl::Caps &caps) const; + GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; + GLuint getUsedSamplerRange(gl::SamplerType type) const; + void updateSamplerMapping(); + + bool usesPointSize() const { return mUsesPointSize; } + bool usesPointSpriteEmulation() const; + bool usesGeometryShader(GLenum drawMode) const; + bool usesInstancedPointSpriteEmulation() const; + + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; + gl::Error save(gl::BinaryOutputStream *stream) override; + void setBinaryRetrievableHint(bool retrievable) override; + + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getGeometryExecutableForPrimitiveType(const gl::ContextState &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog); + + LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override; + GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; + + bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; + bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const override; + void setPathFragmentInputGen(const std::string &inputName, + GLenum genMode, + GLint components, + const GLfloat *coeffs) override; + + void initializeUniformStorage(); + gl::Error applyUniforms(GLenum drawMode); + gl::Error applyUniformBuffers(const gl::ContextState &data); + void dirtyAllUniforms(); + + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(GLint location, GLsizei count, const GLint *v); + void setUniform2iv(GLint location, GLsizei count, const GLint *v); + void setUniform3iv(GLint location, GLsizei count, const GLint *v); + void setUniform4iv(GLint location, GLsizei count, const GLint *v); + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); + void setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + + void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; + + const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } + const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + + unsigned int getSerial() const; + + const AttribIndexArray &getAttribLocationToD3DSemantics() const + { + return mAttribLocationToD3DSemantic; + } + + void updateCachedInputLayout(const gl::State &state); + const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; } + + bool isSamplerMappingDirty() { return mDirtySamplerMapping; } + + private: + class VertexExecutable + { + public: + enum HLSLAttribType + { + FLOAT, + UNSIGNED_INT, + SIGNED_INT, + }; + + typedef std::vector<HLSLAttribType> Signature; + + VertexExecutable(const gl::InputLayout &inputLayout, + const Signature &signature, + ShaderExecutableD3D *shaderExecutable); + ~VertexExecutable(); + + bool matchesSignature(const Signature &signature) const; + static void getSignature(RendererD3D *renderer, + const gl::InputLayout &inputLayout, + Signature *signatureOut); + + const gl::InputLayout &inputs() const { return mInputs; } + const Signature &signature() const { return mSignature; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } + + private: + static HLSLAttribType GetAttribType(GLenum type); + + gl::InputLayout mInputs; + Signature mSignature; + ShaderExecutableD3D *mShaderExecutable; + }; + + class PixelExecutable + { + public: + PixelExecutable(const std::vector<GLenum> &outputSignature, + ShaderExecutableD3D *shaderExecutable); + ~PixelExecutable(); + + bool matchesSignature(const std::vector<GLenum> &signature) const + { + return mOutputSignature == signature; + } + + const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } + + private: + std::vector<GLenum> mOutputSignature; + ShaderExecutableD3D *mShaderExecutable; + }; + + struct Sampler + { + Sampler(); + + bool active; + GLint logicalTextureUnit; + GLenum textureType; + }; + + typedef std::map<std::string, D3DUniform *> D3DUniformMap; + + void defineUniformsAndAssignRegisters(); + void defineUniformBase(const gl::Shader *shader, + const sh::Uniform &uniform, + D3DUniformMap *uniformMap); + void defineUniform(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap); + void assignAllSamplerRegisters(); + void assignSamplerRegisters(D3DUniform *d3dUniform); + + static void AssignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector<Sampler> &outSamplers, + GLuint *outUsedRange); + + template <typename T> + void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType); + + template <int cols, int rows> + void setUniformMatrixfv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType); + + LinkResult compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog); + + void gatherTransformFeedbackVaryings(const VaryingPacking &varyings); + D3DUniform *getD3DUniformByName(const std::string &name); + D3DUniform *getD3DUniformFromLocation(GLint location); + + void initAttribLocationsToD3DSemantic(); + + void reset(); + void assignUniformBlockRegisters(); + + void initUniformBlockInfo(); + size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock); + + RendererD3D *mRenderer; + DynamicHLSL *mDynamicHLSL; + + std::vector<VertexExecutable *> mVertexExecutables; + std::vector<PixelExecutable *> mPixelExecutables; + std::vector<ShaderExecutableD3D *> mGeometryExecutables; + + std::string mVertexHLSL; + D3DCompilerWorkarounds mVertexWorkarounds; + + std::string mPixelHLSL; + D3DCompilerWorkarounds mPixelWorkarounds; + bool mUsesFragDepth; + std::vector<PixelShaderOutputVariable> mPixelShaderKey; + + // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output + // structures, built from the linked varying info. We store the string itself instead of the + // packed varyings for simplicity. + std::string mGeometryShaderPreamble; + + bool mUsesPointSize; + bool mUsesFlatInterpolation; + + UniformStorageD3D *mVertexUniformStorage; + UniformStorageD3D *mFragmentUniformStorage; + + std::vector<Sampler> mSamplersPS; + std::vector<Sampler> mSamplersVS; + GLuint mUsedVertexSamplerRange; + GLuint mUsedPixelSamplerRange; + bool mDirtySamplerMapping; + + // Cache for getPixelExecutableForFramebuffer + std::vector<GLenum> mPixelShaderOutputFormatCache; + + AttribIndexArray mAttribLocationToD3DSemantic; + + unsigned int mSerial; + + std::vector<GLint> mVertexUBOCache; + std::vector<GLint> mFragmentUBOCache; + VertexExecutable::Signature mCachedVertexSignature; + gl::InputLayout mCachedInputLayout; + + std::vector<D3DVarying> mStreamOutVaryings; + std::vector<D3DUniform *> mD3DUniforms; + std::vector<D3DUniformBlock> mD3DUniformBlocks; + + std::map<std::string, sh::BlockMemberInfo> mBlockInfo; + std::map<std::string, size_t> mBlockDataSizes; + + static unsigned int issueSerial(); + static unsigned int mCurrentSerial; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp new file mode 100755 index 000000000..84b30aa10 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012-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. +// + +// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +unsigned int RenderTargetD3D::mCurrentSerial = 1; + +RenderTargetD3D::RenderTargetD3D() + : mSerial(issueSerials(1)) +{ +} + +RenderTargetD3D::~RenderTargetD3D() +{ +} + +unsigned int RenderTargetD3D::getSerial() const +{ + return mSerial; +} + +unsigned int RenderTargetD3D::issueSerials(unsigned int count) +{ + unsigned int firstSerial = mCurrentSerial; + mCurrentSerial += count; + return firstSerial; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h new file mode 100755 index 000000000..c96da5ce1 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2012-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. +// + +// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9 +// and ID3D11View objects belonging to renderbuffers and renderable textures. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/FramebufferAttachment.h" + +namespace rx +{ + +class RenderTargetD3D : public FramebufferAttachmentRenderTarget +{ + public: + RenderTargetD3D(); + virtual ~RenderTargetD3D(); + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLsizei getDepth() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLsizei getSamples() const = 0; + gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } + + virtual unsigned int getSerial() const; + static unsigned int issueSerials(unsigned int count); + + // Only currently applies to D3D11. + virtual void signalDirty() {} + + private: + const unsigned int mSerial; + static unsigned int mCurrentSerial; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp new file mode 100755 index 000000000..b0bf0f9cd --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -0,0 +1,96 @@ +// +// Copyright (c) 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. +// + +// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl + + +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" + +#include "libANGLE/Image.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) + : mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr) +{ +} + +RenderbufferD3D::~RenderbufferD3D() +{ + SafeDelete(mRenderTarget); + mImage = nullptr; +} + +gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height) +{ + return setStorageMultisample(0, internalformat, width, height); +} + +gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) +{ + // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage, but we should create depth and stencil buffers + // as DEPTH24_STENCIL8 + GLenum creationFormat = internalformat; + if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8) + { + creationFormat = GL_DEPTH24_STENCIL8_OES; + } + + // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create + // the specified storage. + // Because ES 3.0 already knows the exact number of supported samples, it would already have been + // validated and generated GL_INVALID_VALUE. + const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat); + if (samples > formatCaps.getMaxSamples()) + { + return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.", + samples, formatCaps.getMaxSamples()); + } + + RenderTargetD3D *newRT = NULL; + ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height), + creationFormat, static_cast<GLsizei>(samples), &newRT)); + + SafeDelete(mRenderTarget); + mImage = nullptr; + mRenderTarget = newRT; + + return gl::NoError(); +} + +gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image) +{ + mImage = GetImplAs<EGLImageD3D>(image); + SafeDelete(mRenderTarget); + + return gl::NoError(); +} + +gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget) +{ + if (mImage) + { + return mImage->getRenderTarget(outRenderTarget); + } + else + { + *outRenderTarget = mRenderTarget; + return gl::NoError(); + } +} + +gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) +{ + return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut)); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h new file mode 100755 index 000000000..20f6a10b2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 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. +// + +// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ + +#include "angle_gl.h" + +#include "common/angleutils.h" +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace rx +{ +class EGLImageD3D; +class RendererD3D; +class RenderTargetD3D; +class SwapChainD3D; + +class RenderbufferD3D : public RenderbufferImpl +{ + public: + RenderbufferD3D(RendererD3D *renderer); + virtual ~RenderbufferD3D(); + + gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; + gl::Error setStorageMultisample(size_t samples, + GLenum internalformat, + size_t width, + size_t height) override; + gl::Error setStorageEGLImageTarget(egl::Image *image) override; + + gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget); + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; + + private: + RendererD3D *mRenderer; + RenderTargetD3D *mRenderTarget; + EGLImageD3D *mImage; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp new file mode 100755 index 000000000..e7e22efc5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -0,0 +1,372 @@ +// +// Copyright (c) 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. +// + +// RendererD3D.cpp: Implementation of the base D3D Renderer. + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +#include "common/debug.h" +#include "common/MemoryBuffer.h" +#include "common/utilities.h" +#include "libANGLE/Display.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" + +namespace rx +{ + +RendererD3D::RendererD3D(egl::Display *display) + : mDisplay(display), + mPresentPathFastEnabled(false), + mCapsInitialized(false), + mWorkaroundsInitialized(false), + mDisjoint(false), + mDeviceLost(false) +{ +} + +RendererD3D::~RendererD3D() +{ + cleanup(); +} + +void RendererD3D::cleanup() +{ + for (auto &incompleteTexture : mIncompleteTextures) + { + incompleteTexture.second.set(nullptr); + } + mIncompleteTextures.clear(); +} + +unsigned int RendererD3D::GetBlendSampleMask(const gl::ContextState &data, int samples) +{ + const auto &glState = data.getState(); + unsigned int mask = 0; + if (glState.isSampleCoverageEnabled()) + { + GLclampf coverageValue = glState.getSampleCoverageValue(); + if (coverageValue != 0) + { + float threshold = 0.5f; + + for (int i = 0; i < samples; ++i) + { + mask <<= 1; + + if ((i + 1) * coverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } + } + + bool coverageInvert = glState.getSampleCoverageInvert(); + if (coverageInvert) + { + mask = ~mask; + } + } + else + { + mask = 0xFFFFFFFF; + } + + return mask; +} + +// 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 RendererD3D::applyTextures(GLImplFactory *implFactory, + const gl::ContextState &data, + gl::SamplerType shaderType, + const FramebufferTextureArray &framebufferTextures, + size_t framebufferTextureCount) +{ + const auto &glState = data.getState(); + const auto &caps = data.getCaps(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + ASSERT(!programD3D->isSamplerMappingDirty()); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); + for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); + if (textureUnit != -1) + { + gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + + gl::Sampler *samplerObject = glState.getSampler(textureUnit); + + const gl::SamplerState &samplerState = + samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); + + // TODO: std::binary_search may become unavailable using older versions of GCC + if (texture->getTextureState().isSamplerComplete(samplerState, data) && + !std::binary_search(framebufferTextures.begin(), + framebufferTextures.begin() + framebufferTextureCount, texture)) + { + ANGLE_TRY(setSamplerState(shaderType, samplerIndex, texture, samplerState)); + ANGLE_TRY(setTexture(shaderType, samplerIndex, texture)); + } + else + { + // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. + gl::Texture *incompleteTexture = getIncompleteTexture(implFactory, textureType); + + ANGLE_TRY(setSamplerState(shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState())); + ANGLE_TRY(setTexture(shaderType, samplerIndex, incompleteTexture)); + } + } + else + { + // No texture bound to this slot even though it is used by the shader, bind a NULL texture + ANGLE_TRY(setTexture(shaderType, samplerIndex, nullptr)); + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits + : caps.maxVertexTextureImageUnits; + clearTextures(shaderType, samplerRange, samplerCount); + + return gl::NoError(); +} + +gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory, const gl::ContextState &data) +{ + FramebufferTextureArray framebufferTextures; + size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures); + + ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_VERTEX, framebufferTextures, + framebufferSerialCount)); + ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_PIXEL, framebufferTextures, + framebufferSerialCount)); + return gl::NoError(); +} + +bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode) +{ + const gl::State &state = data.getState(); + + if (drawMode == GL_POINTS) + { + bool usesPointSize = GetImplAs<ProgramD3D>(state.getProgram())->usesPointSize(); + + // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, + // which affects varying interpolation. Since the value of gl_PointSize is + // undefined when not written, just skip drawing to avoid unexpected results. + if (!usesPointSize && !state.isTransformFeedbackActiveUnpaused()) + { + // This is stictly speaking not an error, but developers should be + // notified of risking undefined behavior. + ERR("Point rendering without writing to gl_PointSize."); + + return true; + } + } + else if (gl::IsTriangleMode(drawMode)) + { + if (state.getRasterizerState().cullFace && + state.getRasterizerState().cullMode == GL_FRONT_AND_BACK) + { + return true; + } + } + + return false; +} + +gl::Error RendererD3D::markTransformFeedbackUsage(const gl::ContextState &data) +{ + const gl::TransformFeedback *transformFeedback = data.getState().getCurrentTransformFeedback(); + for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) + { + const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i); + if (binding.get() != nullptr) + { + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get()); + ANGLE_TRY(bufferD3D->markTransformFeedbackUsage()); + } + } + + return gl::NoError(); +} + +size_t RendererD3D::getBoundFramebufferTextures(const gl::ContextState &data, + FramebufferTextureArray *outTextureArray) +{ + size_t textureCount = 0; + + const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer(); + for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++) + { + const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->type() == GL_TEXTURE) + { + (*outTextureArray)[textureCount++] = attachment->getTexture(); + } + } + + const gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE) + { + (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture(); + } + + std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount); + + return textureCount; +} + +gl::Texture *RendererD3D::getIncompleteTexture(GLImplFactory *implFactory, GLenum type) +{ + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) + { + const GLubyte color[] = { 0, 0, 0, 255 }; + const gl::Extents colorSize(1, 1, 1); + const gl::PixelUnpackState unpack(1, 0); + const gl::Box area(0, 0, 0, 1, 1, 1); + + // If a texture is external use a 2D texture for the incomplete texture + GLenum createType = (type == GL_TEXTURE_EXTERNAL_OES) ? GL_TEXTURE_2D : type; + + // Skip the API layer to avoid needing to pass the Context and mess with dirty bits. + gl::Texture *t = + new gl::Texture(implFactory, std::numeric_limits<GLuint>::max(), createType); + t->setStorage(createType, 1, GL_RGBA8, colorSize); + if (type == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) + { + t->getImplementation()->setSubImage(face, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, + unpack, color); + } + } + else + { + t->getImplementation()->setSubImage(createType, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, unpack, + color); + } + mIncompleteTextures[type].set(t); + } + + return mIncompleteTextures[type].get(); +} + +GLenum RendererD3D::getResetStatus() +{ + if (!mDeviceLost) + { + if (testDeviceLost()) + { + mDeviceLost = true; + notifyDeviceLost(); + return GL_UNKNOWN_CONTEXT_RESET_EXT; + } + return GL_NO_ERROR; + } + + if (testDeviceResettable()) + { + return GL_NO_ERROR; + } + + return GL_UNKNOWN_CONTEXT_RESET_EXT; +} + +void RendererD3D::notifyDeviceLost() +{ + mDisplay->notifyDeviceLost(); +} + +std::string RendererD3D::getVendorString() const +{ + LUID adapterLuid = { 0 }; + + if (getLUID(&adapterLuid)) + { + char adapterLuidString[64]; + sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + return std::string(adapterLuidString); + } + + return std::string(""); +} + +void RendererD3D::setGPUDisjoint() +{ + mDisjoint = true; +} + +GLint RendererD3D::getGPUDisjoint() +{ + bool disjoint = mDisjoint; + + // Disjoint flag is cleared when read + mDisjoint = false; + + return disjoint; +} + +GLint64 RendererD3D::getTimestamp() +{ + // D3D has no way to get an actual timestamp reliably so 0 is returned + return 0; +} + +void RendererD3D::ensureCapsInitialized() const +{ + if (!mCapsInitialized) + { + generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations); + mCapsInitialized = true; + } +} + +const gl::Caps &RendererD3D::getNativeCaps() const +{ + ensureCapsInitialized(); + return mNativeCaps; +} + +const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const +{ + ensureCapsInitialized(); + return mNativeTextureCaps; +} + +const gl::Extensions &RendererD3D::getNativeExtensions() const +{ + ensureCapsInitialized(); + return mNativeExtensions; +} + +const gl::Limitations &RendererD3D::getNativeLimitations() const +{ + ensureCapsInitialized(); + return mNativeLimitations; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h new file mode 100755 index 000000000..b63aba8a9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -0,0 +1,317 @@ + +// Copyright (c) 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. +// + +// RendererD3D.h: Defines a back-end specific class for the DirectX renderer. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ + +#include "common/debug.h" +#include "common/MemoryBuffer.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/Device.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" +#include "libANGLE/Version.h" + +//FIXME(jmadill): std::array is currently prohibited by Chromium style guide +#include <array> + +namespace egl +{ +class ConfigSet; +} + +namespace gl +{ +class FramebufferState; +class InfoLog; +class Texture; +struct LinkedVarying; +} + +namespace rx +{ +class ContextImpl; +struct D3DUniform; +struct D3DVarying; +class DeviceD3D; +class EGLImageD3D; +class FramebufferImpl; +class ImageD3D; +class IndexBuffer; +class NativeWindowD3D; +class ProgramD3D; +class RenderTargetD3D; +class ShaderExecutableD3D; +class SwapChainD3D; +class TextureStorage; +struct TranslatedIndexData; +class UniformStorageD3D; +class VertexBuffer; + +enum ShaderType +{ + SHADER_VERTEX, + SHADER_PIXEL, + SHADER_GEOMETRY, + SHADER_TYPE_MAX +}; + +struct DeviceIdentifier +{ + UINT VendorId; + UINT DeviceId; + UINT SubSysId; + UINT Revision; + UINT FeatureLevel; +}; + +enum RendererClass +{ + RENDERER_D3D11, + RENDERER_D3D9 +}; + +// Useful for unit testing +class BufferFactoryD3D : angle::NonCopyable +{ + public: + BufferFactoryD3D() {} + virtual ~BufferFactoryD3D() {} + + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + + // TODO(jmadill): add VertexFormatCaps + virtual VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const = 0; + virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0; + virtual gl::ErrorOrResult<unsigned int> getVertexSpaceRequired( + const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const = 0; +}; + +using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>; + +class RendererD3D : public BufferFactoryD3D +{ + public: + explicit RendererD3D(egl::Display *display); + virtual ~RendererD3D(); + + virtual egl::Error initialize() = 0; + + virtual egl::ConfigSet generateConfigs() = 0; + virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0; + + virtual ContextImpl *createContext(const gl::ContextState &state) = 0; + + std::string getVendorString() const; + + virtual int getMinorShaderModel() const = 0; + virtual std::string getShaderModelSuffix() const = 0; + + // Direct3D Specific methods + virtual DeviceIdentifier getAdapterIdentifier() const = 0; + + virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0; + virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const = 0; + + virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) = 0; + virtual egl::Error getD3DTextureInfo(IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const = 0; + virtual egl::Error validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const = 0; + + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + + virtual gl::Error setUniformBuffers(const gl::ContextState &data, + const std::vector<GLint> &vertexUniformBuffers, + const std::vector<GLint> &fragmentUniformBuffers) = 0; + + virtual gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector<D3DUniform *> &uniformArray) = 0; + + virtual unsigned int getReservedVertexUniformBuffers() const = 0; + virtual unsigned int getReservedFragmentUniformBuffers() const = 0; + + virtual int getMajorShaderModel() const = 0; + + const WorkaroundsD3D &getWorkarounds() const; + + // Pixel operations + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0; + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + + virtual gl::Error copyTexture(const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) = 0; + virtual gl::Error copyCompressedTexture(const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) = 0; + + // RenderTarget creation + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0; + virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0; + + // Shader operations + virtual gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) = 0; + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) = 0; + virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; + + // Image operations + virtual ImageD3D *createImage() = 0; + virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0; + virtual gl::Error generateMipmapUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; + virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) = 0; + virtual TextureStorage *createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0; + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; + + // Device lost + GLenum getResetStatus(); + void notifyDeviceLost(); + virtual bool resetDevice() = 0; + virtual bool testDeviceLost() = 0; + virtual bool testDeviceResettable() = 0; + + virtual RendererClass getRendererClass() const = 0; + virtual void *getD3DDevice() = 0; + + void setGPUDisjoint(); + + GLint getGPUDisjoint(); + GLint64 getTimestamp(); + + // In D3D11, faster than calling setTexture a jillion times + virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0; + + virtual egl::Error getEGLDevice(DeviceImpl **device) = 0; + + bool presentPathFastEnabled() const { return mPresentPathFastEnabled; } + + // Stream creation + virtual StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) = 0; + + const gl::Caps &getNativeCaps() const; + const gl::TextureCapsMap &getNativeTextureCaps() const; + const gl::Extensions &getNativeExtensions() const; + const gl::Limitations &getNativeLimitations() const; + + // Necessary hack for default framebuffers in D3D. + virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0; + + virtual gl::Version getMaxSupportedESVersion() const = 0; + + protected: + virtual bool getLUID(LUID *adapterLuid) const = 0; + virtual void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const = 0; + + void cleanup(); + + static unsigned int GetBlendSampleMask(const gl::ContextState &data, int samples); + // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. + + gl::Error applyTextures(GLImplFactory *implFactory, const gl::ContextState &data); + bool skipDraw(const gl::ContextState &data, GLenum drawMode); + gl::Error markTransformFeedbackUsage(const gl::ContextState &data); + + egl::Display *mDisplay; + + bool mPresentPathFastEnabled; + + private: + void ensureCapsInitialized() const; + + typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray; + + gl::Error applyTextures(GLImplFactory *implFactory, + const gl::ContextState &data, + gl::SamplerType shaderType, + const FramebufferTextureArray &framebufferTextures, + size_t framebufferTextureCount); + + size_t getBoundFramebufferTextures(const gl::ContextState &data, + FramebufferTextureArray *outTextureArray); + gl::Texture *getIncompleteTexture(GLImplFactory *implFactory, GLenum type); + + virtual WorkaroundsD3D generateWorkarounds() const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mNativeCaps; + mutable gl::TextureCapsMap mNativeTextureCaps; + mutable gl::Extensions mNativeExtensions; + mutable gl::Limitations mNativeLimitations; + + gl::TextureMap mIncompleteTextures; + + mutable bool mWorkaroundsInitialized; + mutable WorkaroundsD3D mWorkarounds; + + bool mDisjoint; + bool mDeviceLost; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h new file mode 100755 index 000000000..7aabdc813 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h @@ -0,0 +1,25 @@ +// +// Copyright 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. +// + +// SamplerD3D.h: Defines the rx::SamplerD3D class, an implementation of SamplerImpl. + +#ifndef LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ +#define LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ + +#include "libANGLE/renderer/SamplerImpl.h" + +namespace rx +{ + +class SamplerD3D : public SamplerImpl +{ + public: + SamplerD3D() {} + ~SamplerD3D() override {} +}; +} + +#endif // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp new file mode 100755 index 000000000..fd7b13abb --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -0,0 +1,227 @@ +// +// Copyright (c) 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. +// + +// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#include "libANGLE/renderer/d3d/ShaderD3D.h" + +#include "common/utilities.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Shader.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" + +// Definitions local to the translation unit +namespace +{ + +const char *GetShaderTypeString(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return "VERTEX"; + + case GL_FRAGMENT_SHADER: + return "FRAGMENT"; + + default: + UNREACHABLE(); + return ""; + } +} + +} // anonymous namespace + +namespace rx +{ + +ShaderD3D::ShaderD3D(const gl::ShaderState &data, const WorkaroundsD3D &workarounds) + : ShaderImpl(data), mAdditionalOptions(0) +{ + uncompile(); + + if (workarounds.expandIntegerPowExpressions) + { + mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS; + } + + if (workarounds.getDimensionsIgnoresBaseLevel) + { + mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL; + } + + if (workarounds.preAddTexelFetchOffsets) + { + mAdditionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH; + } + if (workarounds.rewriteUnaryMinusOperator) + { + mAdditionalOptions |= SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR; + } + if (workarounds.emulateIsnanFloat) + { + mAdditionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION; + } +} + +ShaderD3D::~ShaderD3D() +{ +} + +std::string ShaderD3D::getDebugInfo() const +{ + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) + + " SHADER END\n"; +} + +// initialize/clean up previous state +void ShaderD3D::uncompile() +{ + // set by compileToHLSL + mCompilerOutputType = SH_ESSL_OUTPUT; + + mUsesMultipleRenderTargets = false; + mUsesFragColor = false; + mUsesFragData = false; + mUsesFragCoord = false; + mUsesFrontFacing = false; + mUsesPointSize = false; + mUsesPointCoord = false; + mUsesDepthRange = false; + mUsesFragDepth = false; + mUsesDiscardRewriting = false; + mUsesNestedBreak = false; + mRequiresIEEEStrictCompiling = false; + + mDebugInfo.clear(); +} + +void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const +{ + if (mUsesDiscardRewriting) + { + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + workarounds->skipOptimization = true; + } + else if (mUsesNestedBreak) + { + // ANGLE issue 603: + // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization + // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence + workarounds->useMaxOptimization = true; + } + + if (mRequiresIEEEStrictCompiling) + { + // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work. + workarounds->enableIEEEStrictness = true; + } +} + +unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const +{ + ASSERT(mUniformRegisterMap.count(uniformName) > 0); + return mUniformRegisterMap.find(uniformName)->second; +} + +unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const +{ + ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); + return mInterfaceBlockRegisterMap.find(blockName)->second; +} + +ShShaderOutput ShaderD3D::getCompilerOutputType() const +{ + return mCompilerOutputType; +} + +ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream, + std::string *sourcePath) +{ + uncompile(); + + ShCompileOptions additionalOptions = 0; + + const std::string &source = mData.getSource(); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (gl::DebugAnnotationsActive()) + { + *sourcePath = getTempPath(); + writeFile(sourcePath->c_str(), source.c_str(), source.length()); + additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH; + } +#endif + + additionalOptions |= mAdditionalOptions; + + *shaderSourceStream << source; + return additionalOptions; +} + +bool ShaderD3D::hasUniform(const D3DUniform *d3dUniform) const +{ + return mUniformRegisterMap.find(d3dUniform->name) != mUniformRegisterMap.end(); +} + +const std::map<std::string, unsigned int> &GetUniformRegisterMap( + const std::map<std::string, unsigned int> *uniformRegisterMap) +{ + ASSERT(uniformRegisterMap); + return *uniformRegisterMap; +} + +bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) +{ + // TODO(jmadill): We shouldn't need to cache this. + mCompilerOutputType = compiler->getShaderOutputType(); + + const std::string &translatedSource = mData.getTranslatedSource(); + + mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos; + mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; + mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; + mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; + mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; + mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; + mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos; + mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; + mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mUsesDiscardRewriting = + translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; + mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + mRequiresIEEEStrictCompiling = + translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; + + ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType()); + + mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle)); + + for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks()) + { + if (interfaceBlock.staticUse) + { + unsigned int index = static_cast<unsigned int>(-1); + bool blockRegisterResult = + sh::GetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index); + ASSERT(blockRegisterResult); + + mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + } + } + + mDebugInfo += + std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n"; + mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n"; + mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n"; + // Successive steps will append more info + return true; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h new file mode 100755 index 000000000..587c12173 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -0,0 +1,84 @@ +// +// Copyright (c) 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. +// + +// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_ + +#include "libANGLE/renderer/ShaderImpl.h" + +#include <map> + +namespace rx +{ +class DynamicHLSL; +class RendererD3D; +struct D3DCompilerWorkarounds; +struct D3DUniform; +struct WorkaroundsD3D; + +class ShaderD3D : public ShaderImpl +{ + public: + ShaderD3D(const gl::ShaderState &data, const WorkaroundsD3D &workarounds); + virtual ~ShaderD3D(); + + // ShaderImpl implementation + ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) override; + bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; + std::string getDebugInfo() const override; + + // D3D-specific methods + void uncompile(); + + bool hasUniform(const D3DUniform *d3dUniform) const; + + // Query regular uniforms with their name. Query sampler fields of structs with field selection + // using dot (.) operator. + unsigned int getUniformRegister(const std::string &uniformName) const; + + unsigned int getInterfaceBlockRegister(const std::string &blockName) const; + void appendDebugInfo(const std::string &info) const { mDebugInfo += info; } + + void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; + + bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; } + bool usesFragColor() const { return mUsesFragColor; } + bool usesFragData() const { return mUsesFragData; } + bool usesFragCoord() const { return mUsesFragCoord; } + bool usesFrontFacing() const { return mUsesFrontFacing; } + bool usesPointSize() const { return mUsesPointSize; } + bool usesPointCoord() const { return mUsesPointCoord; } + bool usesDepthRange() const { return mUsesDepthRange; } + bool usesFragDepth() const { return mUsesFragDepth; } + + ShShaderOutput getCompilerOutputType() const; + + private: + bool mUsesMultipleRenderTargets; + bool mUsesFragColor; + bool mUsesFragData; + bool mUsesFragCoord; + bool mUsesFrontFacing; + bool mUsesPointSize; + bool mUsesPointCoord; + bool mUsesDepthRange; + bool mUsesFragDepth; + bool mUsesDiscardRewriting; + bool mUsesNestedBreak; + bool mRequiresIEEEStrictCompiling; + + ShShaderOutput mCompilerOutputType; + mutable std::string mDebugInfo; + std::map<std::string, unsigned int> mUniformRegisterMap; + std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; + ShCompileOptions mAdditionalOptions; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp new file mode 100755 index 000000000..97ffdf509 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012-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. +// + +// ShaderExecutable.cpp: Implements a class to contain D3D shader executable +// implementation details. + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +#include "common/angleutils.h" + +namespace rx +{ + +ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length) + : mFunctionBuffer(length) +{ + memcpy(mFunctionBuffer.data(), function, length); +} + +ShaderExecutableD3D::~ShaderExecutableD3D() +{ +} + +const uint8_t *ShaderExecutableD3D::getFunction() const +{ + return mFunctionBuffer.data(); +} + +size_t ShaderExecutableD3D::getLength() const +{ + return mFunctionBuffer.size(); +} + +const std::string &ShaderExecutableD3D::getDebugInfo() const +{ + return mDebugInfo; +} + +void ShaderExecutableD3D::appendDebugInfo(const std::string &info) +{ + mDebugInfo += info; +} + + +UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize) +{ +} + +UniformStorageD3D::~UniformStorageD3D() +{ +} + +size_t UniformStorageD3D::size() const +{ + return mSize; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h new file mode 100755 index 000000000..71b83b795 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2012-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. +// + +// ShaderExecutable.h: Defines a class to contain D3D shader executable +// implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ + +#include "common/debug.h" + +#include <vector> +#include <cstdint> + +namespace rx +{ + +class ShaderExecutableD3D : angle::NonCopyable +{ + public: + ShaderExecutableD3D(const void *function, size_t length); + virtual ~ShaderExecutableD3D(); + + const uint8_t *getFunction() const; + + size_t getLength() const; + + const std::string &getDebugInfo() const; + + void appendDebugInfo(const std::string &info); + + private: + std::vector<uint8_t> mFunctionBuffer; + std::string mDebugInfo; +}; + +class UniformStorageD3D : angle::NonCopyable +{ + public: + UniformStorageD3D(size_t initialSize); + virtual ~UniformStorageD3D(); + + size_t size() const; + + private: + size_t mSize; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp new file mode 100755 index 000000000..8696ab0d7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -0,0 +1,402 @@ +// +// Copyright (c) 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. +// + +// SurfaceD3D.cpp: D3D implementation of an EGL surface + +#include "libANGLE/renderer/d3d/SurfaceD3D.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +#include <tchar.h> +#include <EGL/eglext.h> +#include <algorithm> + +namespace rx +{ + +SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) + : SurfaceImpl(state), + mRenderer(renderer), + mDisplay(display), + mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE), + mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))), + mRenderTargetFormat(config->renderTargetFormat), + mDepthStencilFormat(config->depthStencilFormat), + mSwapChain(nullptr), + mSwapIntervalDirty(true), + mNativeWindow(renderer->createNativeWindow(window, config, attribs)), + mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))), + mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))), + mSwapInterval(1), + mShareHandle(0), + mD3DTexture(nullptr) +{ + if (window != nullptr && !mFixedSize) + { + mWidth = -1; + mHeight = -1; + } + + switch (buftype) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + mShareHandle = static_cast<HANDLE>(clientBuffer); + break; + + case EGL_D3D_TEXTURE_ANGLE: + mD3DTexture = static_cast<IUnknown *>(clientBuffer); + ASSERT(mD3DTexture != nullptr); + mD3DTexture->AddRef(); + mRenderer->getD3DTextureInfo(mD3DTexture, &mWidth, &mHeight, &mRenderTargetFormat); + mDepthStencilFormat = GL_NONE; + break; + + default: + break; + } +} + +SurfaceD3D::~SurfaceD3D() +{ + releaseSwapChain(); + SafeDelete(mNativeWindow); + SafeRelease(mD3DTexture); +} + +void SurfaceD3D::releaseSwapChain() +{ + SafeDelete(mSwapChain); +} + +egl::Error SurfaceD3D::initialize() +{ + if (mNativeWindow->getNativeWindow()) + { + if (!mNativeWindow->initialize()) + { + return egl::Error(EGL_BAD_SURFACE); + } + } + + egl::Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data) +{ + return mRenderer->createDefaultFramebuffer(data); +} + +egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::releaseTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain() +{ + ASSERT(!mSwapChain); + + int width; + int height; + + if (!mFixedSize) + { + RECT windowRect; + if (!mNativeWindow->getClientRect(&windowRect)) + { + ASSERT(false); + + return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); + } + + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + else + { + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; + } + + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, + mRenderTargetFormat, mDepthStencilFormat, mOrientation); + if (!mSwapChain) + { + return egl::Error(EGL_BAD_ALLOC); + } + + egl::Error error = resetSwapChain(width, height); + if (error.isError()) + { + SafeDelete(mSwapChain); + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); + + if (status == EGL_CONTEXT_LOST) + { + mDisplay->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapIntervalDirty = false; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return egl::Error(EGL_SUCCESS); + } + + if (x + width > mWidth) + { + width = mWidth - x; + } + + if (y + height > mHeight) + { + height = mHeight - y; + } + + if (width != 0 && height != 0) + { + EGLint status = mSwapChain->swapRect(x, y, width, height); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + } + + checkForOutOfDateSwapChain(); + + return egl::Error(EGL_SUCCESS); +} + +bool SurfaceD3D::checkForOutOfDateSwapChain() +{ + RECT client; + int clientWidth = getWidth(); + int clientHeight = getHeight(); + bool sizeDirty = false; + if (!mFixedSize && !mNativeWindow->isIconic()) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + if (!mNativeWindow->getClientRect(&client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + clientWidth = client.right - client.left; + clientHeight = client.bottom - client.top; + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + } + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + + if (mSwapIntervalDirty) + { + resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + return wasDirty; +} + +egl::Error SurfaceD3D::swap() +{ + return swapRect(0, 0, mWidth, mHeight); +} + +egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return swapRect(x, y, width, height); +} + +rx::SwapChainD3D *SurfaceD3D::getSwapChain() const +{ + return mSwapChain; +} + +void SurfaceD3D::setSwapInterval(EGLint interval) +{ + if (mSwapInterval == interval) + { + return; + } + + mSwapInterval = interval; + mSwapIntervalDirty = true; +} + +EGLint SurfaceD3D::getWidth() const +{ + return mWidth; +} + +EGLint SurfaceD3D::getHeight() const +{ + return mHeight; +} + +EGLint SurfaceD3D::isPostSubBufferSupported() const +{ + // post sub buffer is always possible on D3D surfaces + return EGL_TRUE; +} + +EGLint SurfaceD3D::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + { + *value = mSwapChain->getShareHandle(); + } + else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE) + { + *value = mSwapChain->getKeyedMutex(); + } + else UNREACHABLE(); + + return egl::Error(EGL_SUCCESS); +} + +gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) +{ + if (target.binding() == GL_BACK) + { + *rtOut = mSwapChain->getColorRenderTarget(); + } + else + { + *rtOut = mSwapChain->getDepthStencilRenderTarget(); + } + return gl::Error(GL_NO_ERROR); +} + +WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) + : SurfaceD3D(state, + renderer, + display, + config, + window, + 0, + static_cast<EGLClientBuffer>(0), + attribs) +{ +} + +WindowSurfaceD3D::~WindowSurfaceD3D() +{ +} + +PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) + : SurfaceD3D(state, + renderer, + display, + config, + static_cast<EGLNativeWindowType>(0), + buftype, + clientBuffer, + attribs) +{ +} + +PbufferSurfaceD3D::~PbufferSurfaceD3D() +{ +} + +} // namespace rc diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h new file mode 100755 index 000000000..768c60bd0 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -0,0 +1,121 @@ +// +// Copyright (c) 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. +// + +// SurfaceD3D.h: D3D implementation of an EGL surface + +#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_ +#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_ + +#include "libANGLE/renderer/SurfaceImpl.h" +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" + +namespace egl +{ +class Surface; +} + +namespace rx +{ +class SwapChainD3D; +class RendererD3D; + +class SurfaceD3D : public SurfaceImpl +{ + public: + ~SurfaceD3D() override; + void releaseSwapChain(); + + egl::Error initialize() override; + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + // D3D implementations + SwapChainD3D *getSwapChain() const; + + egl::Error resetSwapChain(); + + // Returns true if swapchain changed due to resize or interval update + bool checkForOutOfDateSwapChain(); + + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; + + protected: + SurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs); + + egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight); + egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight); + + RendererD3D *mRenderer; + egl::Display *mDisplay; + + bool mFixedSize; + GLint mOrientation; + + GLenum mRenderTargetFormat; + GLenum mDepthStencilFormat; + + SwapChainD3D *mSwapChain; + bool mSwapIntervalDirty; + + NativeWindowD3D *mNativeWindow; // Handler for the Window that the surface is created for. + EGLint mWidth; + EGLint mHeight; + + EGLint mSwapInterval; + + HANDLE mShareHandle; + IUnknown *mD3DTexture; +}; + +class WindowSurfaceD3D : public SurfaceD3D +{ + public: + WindowSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + const egl::AttributeMap &attribs); + ~WindowSurfaceD3D() override; +}; + +class PbufferSurfaceD3D : public SurfaceD3D +{ + public: + PbufferSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs); + ~PbufferSurfaceD3D() override; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp new file mode 100644 index 000000000..de8534c3d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2016 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. +// + +// SwapChainD3D.cpp: Defines a back-end specific class that hides the details of the +// implementation-specific swapchain. + +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +namespace rx +{ + +SwapChainD3D::SwapChainD3D(HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat) + : mOffscreenRenderTargetFormat(backBufferFormat), + mDepthBufferFormat(depthBufferFormat), + mShareHandle(shareHandle), + mD3DTexture(d3dTexture) +{ + if (mD3DTexture) + { + mD3DTexture->AddRef(); + } +} + +SwapChainD3D::~SwapChainD3D() +{ + SafeRelease(mD3DTexture); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h new file mode 100755 index 000000000..f49204527 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2012 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. +// + +// SwapChainD3D.h: Defines a back-end specific class that hides the details of the +// implementation-specific swapchain. + +#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ +#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ + +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +#include "common/angleutils.h" +#include "common/platform.h" + +#if !defined(ANGLE_FORCE_VSYNC_OFF) +#define ANGLE_FORCE_VSYNC_OFF 0 +#endif + +namespace rx +{ +class RenderTargetD3D; + +class SwapChainD3D : angle::NonCopyable +{ + public: + SwapChainD3D(HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat); + virtual ~SwapChainD3D(); + + virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual void recreate() = 0; + + virtual RenderTargetD3D *getColorRenderTarget() = 0; + virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; + + GLenum getRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; } + GLenum getDepthBufferInternalFormat() const { return mDepthBufferFormat; } + + HANDLE getShareHandle() { return mShareHandle; } + virtual void *getKeyedMutex() = 0; + + protected: + const GLenum mOffscreenRenderTargetFormat; + const GLenum mDepthBufferFormat; + + HANDLE mShareHandle; + IUnknown *mD3DTexture; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp new file mode 100755 index 000000000..287700264 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -0,0 +1,3086 @@ +// +// Copyright 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. +// + +// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#include "libANGLE/renderer/d3d/TextureD3D.h" + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Config.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Image.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" + +namespace rx +{ + +namespace +{ + +gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset, const uint8_t **pointerOut) +{ + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels); + + // TODO: this is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(pixelBuffer); + ASSERT(bufferD3D); + const uint8_t *bufferData = NULL; + ANGLE_TRY(bufferD3D->getData(&bufferData)); + *pointerOut = bufferData + offset; + } + else + { + *pointerOut = pixels; + } + + // Offset the pointer for 2D array layer (if it's valid) + if (*pointerOut != nullptr) + { + *pointerOut += layerOffset; + } + + return gl::Error(GL_NO_ERROR); +} + +bool IsRenderTargetUsage(GLenum usage) +{ + return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); +} + +} + +TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer) + : TextureImpl(state), + mRenderer(renderer), + mDirtyImages(true), + mImmutable(false), + mTexStorage(nullptr), + mBaseLevel(0) +{ +} + +TextureD3D::~TextureD3D() +{ +} + +gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage) +{ + // ensure the underlying texture is created + ANGLE_TRY(initializeStorage(false)); + + if (mTexStorage) + { + ANGLE_TRY(updateStorage()); + } + + ASSERT(outStorage); + + *outStorage = mTexStorage; + return gl::NoError(); +} + +GLint TextureD3D::getLevelZeroWidth() const +{ + ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelWidth())) > getBaseLevel()); + return getBaseLevelWidth() << mBaseLevel; +} + +GLint TextureD3D::getLevelZeroHeight() const +{ + ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelHeight())) > getBaseLevel()); + return getBaseLevelHeight() << mBaseLevel; +} + +GLint TextureD3D::getLevelZeroDepth() const +{ + return getBaseLevelDepth(); +} + +GLint TextureD3D::getBaseLevelWidth() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); +} + +GLint TextureD3D::getBaseLevelHeight() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); +} + +GLint TextureD3D::getBaseLevelDepth() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); +} + +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum TextureD3D::getBaseLevelInternalFormat() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); +} + +bool TextureD3D::shouldUseSetData(const ImageD3D *image) const +{ + if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) + { + return false; + } + + gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat()); + + // We can only handle full updates for depth-stencil textures, so to avoid complications + // disable them entirely. + if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0) + { + return false; + } + + // TODO(jmadill): Handle compressed internal formats + return (mTexStorage && !internalFormat.compressed); +} + +gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset) +{ + ImageD3D *image = getImage(index); + ASSERT(image); + + // No-op + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return gl::Error(GL_NO_ERROR); + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const uint8_t *pixelData = NULL; + ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData)); + + if (pixelData != nullptr) + { + if (shouldUseSetData(image)) + { + ANGLE_TRY(mTexStorage->setData(index, image, NULL, type, unpack, pixelData)); + } + else + { + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + ANGLE_TRY(image->loadData(fullImageArea, unpack, type, pixelData, index.is3D())); + } + + mDirtyImages = true; + } + + return gl::NoError(); +} + +gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) +{ + // CPU readback & copy where direct GPU copy is not supported + const uint8_t *pixelData = NULL; + ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData)); + + if (pixelData != NULL) + { + ImageD3D *image = getImage(index); + ASSERT(image); + + if (shouldUseSetData(image)) + { + return mTexStorage->setData(index, image, &area, type, unpack, pixelData); + } + + ANGLE_TRY(image->loadData(area, unpack, type, pixelData, index.is3D())); + ANGLE_TRY(commitRegion(index, area)); + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset) +{ + ImageD3D *image = getImage(index); + ASSERT(image); + + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return gl::NoError(); + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const uint8_t *pixelData = NULL; + ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData)); + + if (pixelData != NULL) + { + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + ANGLE_TRY(image->loadCompressedData(fullImageArea, pixelData)); + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset) +{ + const uint8_t *pixelData = NULL; + ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData)); + + if (pixelData != NULL) + { + ImageD3D *image = getImage(index); + ASSERT(image); + + ANGLE_TRY(image->loadCompressedData(area, pixelData)); + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +{ + return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); +} + +gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget) +{ + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || + unpack.skipImages != 0) + { + // TODO(jmadill): additional unpack parameters + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, + "Unimplemented pixel store parameters in fastUnpackPixels"); + } + + // No-op + if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) + { + return gl::Error(GL_NO_ERROR); + } + + // In order to perform the fast copy through the shader, we must have the right format, and be able + // to create a render target. + ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); + + uintptr_t offset = reinterpret_cast<uintptr_t>(pixels); + + ANGLE_TRY(mRenderer->fastCopyBufferToTexture(unpack, static_cast<unsigned int>(offset), + destRenderTarget, sizedInternalFormat, type, + destArea)); + + return gl::NoError(); +} + +GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const +{ + if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || + mRenderer->getNativeExtensions().textureNPOT) + { + // Maximum number of levels + return gl::log2(std::max(std::max(width, height), depth)) + 1; + } + else + { + // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. + return 1; + } +} + +TextureStorage *TextureD3D::getStorage() +{ + ASSERT(mTexStorage); + return mTexStorage; +} + +ImageD3D *TextureD3D::getBaseLevelImage() const +{ + if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return nullptr; + } + return getImage(getImageIndex(mBaseLevel, 0)); +} + +gl::Error TextureD3D::setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + // Only external images can accept external textures + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D::generateMipmap() +{ + const GLuint baseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + ASSERT(maxLevel > baseLevel); // Should be checked before calling this. + + if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // Switch to using the mipmapped texture. + TextureStorage *textureStorage = NULL; + ANGLE_TRY(getNativeTexture(&textureStorage)); + ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(false)); + } + + // Set up proper mipmap chain in our Image array. + initMipmapImages(); + + if (mTexStorage && mTexStorage->supportsNativeMipmapFunction()) + { + ANGLE_TRY(updateStorage()); + + // Generate the mipmap chain using the ad-hoc DirectX function. + ANGLE_TRY(mRenderer->generateMipmapUsingD3D(mTexStorage, mState)); + } + else + { + // Generate the mipmap chain, one level at a time. + ANGLE_TRY(generateMipmapUsingImages(maxLevel)); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::generateMipmapUsingImages(const GLuint maxLevel) +{ + // We know that all layers have the same dimension, for the texture to be complete + GLint layerCount = static_cast<GLint>(getLayerCount(mBaseLevel)); + + // When making mipmaps with the setData workaround enabled, the texture storage has + // the image data already. For non-render-target storage, we have to pull it out into + // an image layer. + if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage) + { + if (!mTexStorage->isRenderTarget()) + { + // Copy from the storage mip 0 to Image mip 0 + for (GLint layer = 0; layer < layerCount; ++layer) + { + gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer); + + ImageD3D *image = getImage(srcIndex); + ANGLE_TRY(image->copyFromTexStorage(srcIndex, mTexStorage)); + } + } + else + { + ANGLE_TRY(updateStorage()); + } + } + + // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround. + // The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture. + // As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work. + // The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter). + // Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else. + bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround)); + + for (GLint layer = 0; layer < layerCount; ++layer) + { + for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip) + { + ASSERT(getLayerCount(mip) == layerCount); + + gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer); + gl::ImageIndex destIndex = getImageIndex(mip, layer); + + if (renderableStorage) + { + // GPU-side mipmapping + ANGLE_TRY(mTexStorage->generateMipmap(sourceIndex, destIndex)); + } + else + { + // CPU-side mipmapping + ANGLE_TRY(mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex))); + } + } + } + + if (mTexStorage) + { + updateStorage(); + } + + return gl::NoError(); +} + +bool TextureD3D::isBaseImageZeroSize() const +{ + ImageD3D *baseImage = getBaseLevelImage(); + + if (!baseImage || baseImage->getWidth() <= 0) + { + return true; + } + + if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0) + { + return true; + } + + return false; +} + +gl::Error TextureD3D::ensureRenderTarget() +{ + ANGLE_TRY(initializeStorage(true)); + + if (!isBaseImageZeroSize()) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorage *newRenderTargetStorage = NULL; + ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage)); + + gl::Error error = mTexStorage->copyToStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + + error = setCompleteTexStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + } + } + + return gl::NoError(); +} + +bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const +{ + ImageD3D *image = getImage(index); + bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); + return (image->isRenderableFormat() && levelsComplete); +} + +gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box ®ion) +{ + if (mTexStorage) + { + ASSERT(isValidIndex(index)); + ImageD3D *image = getImage(index); + ANGLE_TRY(image->copyToStorage(mTexStorage, index, region)); + image->markClean(); + } + + return gl::NoError(); +} + +gl::Error TextureD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) +{ + RenderTargetD3D *rtD3D = nullptr; + gl::Error error = getRenderTarget(target.textureIndex(), &rtD3D); + *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D); + return error; +} + +void TextureD3D::setBaseLevel(GLuint baseLevel) +{ + const int oldStorageWidth = std::max(1, getLevelZeroWidth()); + const int oldStorageHeight = std::max(1, getLevelZeroHeight()); + const int oldStorageDepth = std::max(1, getLevelZeroDepth()); + const int oldStorageFormat = getBaseLevelInternalFormat(); + mBaseLevel = baseLevel; + + // When the base level changes, the texture storage might not be valid anymore, since it could + // have been created based on the dimensions of the previous specified level range. + const int newStorageWidth = std::max(1, getLevelZeroWidth()); + const int newStorageHeight = std::max(1, getLevelZeroHeight()); + const int newStorageDepth = std::max(1, getLevelZeroDepth()); + const int newStorageFormat = getBaseLevelInternalFormat(); + if (mTexStorage && + (newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight || + newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat)) + { + markAllImagesDirty(); + SafeDelete(mTexStorage); + } +} + +void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits) +{ + // TODO(geofflang): Use dirty bits +} + +TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) +{ + mEGLImageTarget = false; + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } +} + +TextureD3D_2D::~TextureD3D_2D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_2D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_2D); + return mImageArray[index.mipIndex]; +} + +GLsizei TextureD3D_2D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_2D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_2D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLenum TextureD3D_2D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_2D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_2D::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + bool fastUnpacked = false; + GLint level = static_cast<GLint>(imageLevel); + + redefineImage(level, sizedInternalFormat, size, false); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + // Attempt a fast gpu copy of the pixel data to the surface + if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTargetD3D *destRenderTarget = NULL; + ANGLE_TRY(getRenderTarget(index, &destRenderTarget)); + + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); + + ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, + destRenderTarget)); + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + + if (!fastUnpacked) + { + ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTargetD3D *renderTarget = NULL; + ANGLE_TRY(getRenderTarget(index, &renderTarget)); + ASSERT(!mImageArray[level]->isDirty()); + + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget); + } + else + { + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + } +} + +gl::Error TextureD3D_2D::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + GLint level = static_cast<GLint>(imageLevel); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size, false); + + return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0); +} + +gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level)); + ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0)); + + return commitRegion(index, area); +} + +gl::Error TextureD3D_2D::copyImage(GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D); + + GLint level = static_cast<GLint>(imageLevel); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1), + false); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Offset destOffset(0, 0, 0); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + mImageArray[level]->markClean(); + + if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level)) + { + ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, + mTexStorage, level)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0); + + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + + if (isValidLevel(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + ANGLE_TRY(mRenderer->copyImage2D( + source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, level)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::copyTexture(GLenum internalFormat, + GLenum type, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + GLenum sourceTarget = source->getTarget(); + GLint sourceLevel = 0; + + GLint destLevel = 0; + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), + static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); + redefineImage(destLevel, sizedInternalFormat, size, false); + + ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel))); + + ANGLE_TRY(ensureRenderTarget()); + ASSERT(isValidLevel(destLevel)); + ANGLE_TRY(updateStorageLevel(destLevel)); + + gl::Rectangle sourceRect(0, 0, size.width, size.height); + gl::Offset destOffset(0, 0, 0); + ANGLE_TRY(mRenderer->copyTexture(source, sourceLevel, sourceRect, + gl::GetInternalFormatInfo(sizedInternalFormat).format, + destOffset, mTexStorage, destLevel, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::copySubTexture(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + GLint sourceLevel = 0; + GLint destLevel = 0; + + ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel))); + + ANGLE_TRY(ensureRenderTarget()); + ASSERT(isValidLevel(destLevel)); + ANGLE_TRY(updateStorageLevel(destLevel)); + + ANGLE_TRY(mRenderer->copyTexture(source, sourceLevel, sourceArea, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, destLevel, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::copyCompressedTexture(const gl::Texture *source) +{ + GLenum sourceTarget = source->getTarget(); + GLint sourceLevel = 0; + + GLint destLevel = 0; + + GLenum sizedInternalFormat = source->getFormat(sourceTarget, sourceLevel).asSized(); + gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), + static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); + redefineImage(destLevel, sizedInternalFormat, size, false); + + ANGLE_TRY(initializeStorage(false)); + ASSERT(mTexStorage); + + ANGLE_TRY(mRenderer->copyCompressedTexture(source, sourceLevel, mTexStorage, destLevel)); + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(GL_TEXTURE_2D && size.depth == 1); + + for (size_t level = 0; level < levels; level++) + { + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); + redefineImage(level, internalFormat, levelSize, true); + } + + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true); + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TextureStorage *storage = mRenderer->createTextureStorage2D( + internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ANGLE_TRY(updateStorage()); + + mImmutable = true; + + return gl::NoError(); +} + +void TextureD3D_2D::bindTexImage(egl::Surface *surface) +{ + GLenum internalformat = surface->getConfig()->renderTargetFormat; + + gl::Extents size(surface->getWidth(), surface->getHeight(), 1); + redefineImage(0, internalformat, size, true); + + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ASSERT(surfaceD3D); + + mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain()); + mEGLImageTarget = false; + + mDirtyImages = true; +} + +void TextureD3D_2D::releaseTexImage() +{ + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true); + } +} + +gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image) +{ + EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image); + + // Set the properties of the base mip level from the EGL image + const auto &format = image->getFormat(); + gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1); + redefineImage(0, format.asSized(), size, true); + + // Clear all other images. + for (size_t level = 1; level < ArraySize(mImageArray); level++) + { + redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true); + } + + SafeDelete(mTexStorage); + mImageArray[0]->markClean(); + + // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error. + RenderTargetD3D *renderTargetD3D = nullptr; + ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D)); + + mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D); + mEGLImageTarget = true; + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2D::initMipmapImages() +{ + const GLuint baseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap + // levels. + for (GLuint level = baseLevel + 1; level <= maxLevel; level++) + { + gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1), + std::max(getLevelZeroHeight() >> level, 1), 1); + + redefineImage(level, getBaseLevelInternalFormat(), levelSize, false); + } +} + +gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + // ensure the underlying texture is created + ANGLE_TRY(ensureRenderTarget()); + ANGLE_TRY(updateStorageLevel(index.mipIndex)); + + return mTexStorage->getRenderTarget(index, outRT); +} + +bool TextureD3D_2D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); +} + +bool TextureD3D_2D::isLevelComplete(int level) const +{ + if (isImmutable()) + { + return true; + } + + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == static_cast<int>(getBaseLevel())) + { + return true; + } + + ASSERT(level >= 0 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr); + ImageD3D *image = mImageArray[level]; + + if (image->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (image->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (image->getHeight() != std::max(1, height >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +// Constructs a native texture resource from the texture images +gl::Error TextureD3D_2D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(getBaseLevel())) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); + + TextureStorage *storage = NULL; + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + ANGLE_TRY(updateStorage()); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +{ + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level)); + } + } + + // TODO(geofflang): Determine if the texture creation succeeded + *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) + { + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) + { + ANGLE_TRY(mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level)); + } + } + + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + mDirtyImages = true; + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + } + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::updateStorageLevel(int level) +{ + ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + ANGLE_TRY(commitRegion(index, region)); + } + + return gl::NoError(); +} + +void TextureD3D_2D::redefineImage(size_t level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) +{ + ASSERT(size.depth == 1); + + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getLevelZeroWidth() >> level); + const int storageHeight = std::max(1, getLevelZeroHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease); + + if (mTexStorage) + { + const size_t storageLevels = mTexStorage->getLevelCount(); + + // If the storage was from an EGL image, copy it back into local images to preserve it + // while orphaning + if (level != 0 && mEGLImageTarget) + { + // TODO(jmadill): Don't discard error. + mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage); + } + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + markAllImagesDirty(); + SafeDelete(mTexStorage); + } + } + + // Can't be an EGL image target after being redefined + mEGLImageTarget = false; +} + +gl::ImageIndexIterator TextureD3D_2D::imageIterator() const +{ + return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); +} + +gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // "layer" does not apply to 2D Textures. + return gl::ImageIndex::Make2D(mip); +} + +bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_2D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +void TextureD3D_2D::markAllImagesDirty() +{ + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + mDirtyImages = true; +} + +TextureD3D_Cube::TextureD3D_Cube(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) +{ + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = renderer->createImage(); + } + } +} + +TextureD3D_Cube::~TextureD3D_Cube() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + SafeDelete(mImageArray[i][j]); + } + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer >= 0 && layer < 6); + return mImageArray[layer][level]; +} + +ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(index.layerIndex >= 0 && index.layerIndex < 6); + return mImageArray[index.layerIndex][index.mipIndex]; +} + +GLsizei TextureD3D_Cube::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 6; +} + +GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[layer][level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; +} + +gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(size.depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); + + redefineImage(index.layerIndex, static_cast<GLint>(level), sizedInternalFormat, size); + + return setImageImpl(index, type, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(size.depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + + redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); + return setCompressedImageImpl(index, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); + + ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0)); + return commitRegion(index, area); +} + +gl::Error TextureD3D_Cube::copyImage(GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + + GLint level = static_cast<GLint>(imageLevel); + + gl::Extents size(sourceArea.width, sourceArea.height, 1); + redefineImage(static_cast<int>(faceIndex), level, sizedInternalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::Offset destOffset(0, 0, 0); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ANGLE_TRY( + mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + mImageArray[faceIndex][level]->markClean(); + + ASSERT(size.width == size.height); + + if (size.width > 0 && isValidFaceLevel(faceIndex, level)) + { + ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, + mTexStorage, target, level)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + gl::Error error = + mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + if (isValidFaceLevel(faceIndex, level)) + { + ANGLE_TRY(updateStorageFaceLevel(faceIndex, level)); + ANGLE_TRY(mRenderer->copyImageCube( + source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, target, level)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(size.width == size.height); + ASSERT(size.depth == 1); + + for (size_t level = 0; level < levels; level++) + { + GLsizei mipSize = std::max(1, size.width >> level); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true); + } + } + + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true); + } + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + + TextureStorage *storage = mRenderer->createTextureStorageCube( + internalFormat, renderTarget, size.width, static_cast<int>(levels), false); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ANGLE_TRY(updateStorage()); + + mImmutable = true; + + return gl::NoError(); +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_Cube::isCubeComplete() const +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + if (baseWidth <= 0 || baseWidth != baseHeight) + { + return false; + } + + for (int faceIndex = 1; faceIndex < 6; faceIndex++) + { + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()]; + + if (faceBaseImage.getWidth() != baseWidth || + faceBaseImage.getHeight() != baseHeight || + faceBaseImage.getInternalFormat() != baseFormat ) + { + return false; + } + } + + return true; +} + +void TextureD3D_Cube::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_Cube::releaseTexImage() +{ + UNREACHABLE(); +} + +void TextureD3D_Cube::initMipmapImages() +{ + const GLuint baseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap + // levels. + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (GLuint level = baseLevel + 1; level <= maxLevel; level++) + { + int faceLevelSize = + (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1)); + redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(), + gl::Extents(faceLevelSize, faceLevelSize, 1)); + } + } +} + +gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(gl::IsCubeMapTextureTarget(index.type)); + + // ensure the underlying texture is created + ANGLE_TRY(ensureRenderTarget()); + ANGLE_TRY(updateStorageFaceLevel(index.layerIndex, index.mipIndex)); + + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::NoError(); + } + + // do not attempt to create storage for nonexistant data + if (!isFaceLevelComplete(0, getBaseLevel())) + { + return gl::NoError(); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); + + TextureStorage *storage = NULL; + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + ANGLE_TRY(updateStorage()); + + return gl::NoError(); +} + +gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +{ + GLsizei size = getLevelZeroWidth(); + + ASSERT(size > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++) + { + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level)); + } + } + } + + // TODO (geofflang): detect if storage creation succeeded + *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) + { + ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube( + newCompleteTexStorage, faceIndex, level)); + } + } + } + + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + mDirtyImages = true; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int face = 0; face < 6; face++) + { + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) + { + ANGLE_TRY(updateStorageFaceLevel(face, level)); + } + } + } + + return gl::NoError(); +} + +bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const +{ + if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return false; + } + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && + mImageArray[faceIndex][level] != nullptr); + + if (isImmutable()) + { + return true; + } + + int levelZeroSize = getLevelZeroWidth(); + + if (levelZeroSize <= 0) + { + return false; + } + + // "isCubeComplete" checks for base level completeness and we must call that + // to determine if any face at level 0 is complete. We omit that check here + // to avoid re-checking cube-completeness for every face at level 0. + if (level == 0) + { + return true; + } + + // Check that non-zero levels are consistent with the base level. + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + + if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const +{ + return isFaceLevelComplete(index.layerIndex, index.mipIndex); +} + +gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ImageD3D *image = mImageArray[faceIndex][level]; + + if (image->isDirty()) + { + GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex); + gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level); + gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1); + ANGLE_TRY(commitRegion(index, region)); + } + + return gl::NoError(); +} + +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getLevelZeroWidth() >> level); + const int storageHeight = std::max(1, getLevelZeroHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + markAllImagesDirty(); + SafeDelete(mTexStorage); + } + } +} + +gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const +{ + return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount()); +} + +gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const +{ + // The "layer" of the image index corresponds to the cube face + return gl::ImageIndex::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip); +} + +bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +void TextureD3D_Cube::markAllImagesDirty() +{ + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) + { + for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++) + { + mImageArray[dirtyFace][dirtyLevel]->markDirty(); + } + } + mDirtyImages = true; +} + +TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } +} + +TextureD3D_3D::~TextureD3D_3D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_3D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_3D); + return mImageArray[index.mipIndex]; +} + +GLsizei TextureD3D_3D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_3D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_3D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLsizei TextureD3D_3D::getDepth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getDepth(); + else + return 0; +} + +GLenum TextureD3D_3D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_3D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_3D::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + GLint level = static_cast<GLint>(imageLevel); + redefineImage(level, sizedInternalFormat, size); + + bool fastUnpacked = false; + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty() && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTargetD3D *destRenderTarget = NULL; + ANGLE_TRY(getRenderTarget(index, &destRenderTarget)); + + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + + ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, + destRenderTarget)); + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + + if (!fastUnpacked) + { + ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0)); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTargetD3D *destRenderTarget = NULL; + ANGLE_TRY(getRenderTarget(index, &destRenderTarget)); + ASSERT(!mImageArray[level]->isDirty()); + + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget); + } + else + { + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + } +} + +gl::Error TextureD3D_3D::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + GLint level = static_cast<GLint>(imageLevel); + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + return setCompressedImageImpl(index, unpack, pixels, 0); +} + +gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level)); + ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0)); + return commitRegion(index, area); +} + +gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); +} + +gl::Error TextureD3D_3D::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_3D); + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + if (canCreateRenderTargetForImage(index)) + { + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + if (isValidLevel(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + ANGLE_TRY(mRenderer->copyImage3D( + source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, level)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(target == GL_TEXTURE_3D); + + for (size_t level = 0; level < levels; level++) + { + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + std::max(1, size.depth >> level)); + mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true); + } + + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true); + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TextureStorage *storage = + mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, + size.depth, static_cast<int>(levels)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ANGLE_TRY(updateStorage()); + + mImmutable = true; + + return gl::NoError(); +} + +void TextureD3D_3D::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_3D::releaseTexImage() +{ + UNREACHABLE(); +} + +void TextureD3D_3D::initMipmapImages() +{ + const GLuint baseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap + // levels. + for (GLuint level = baseLevel + 1; level <= maxLevel; level++) + { + gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1), + std::max(getLevelZeroHeight() >> level, 1), + std::max(getLevelZeroDepth() >> level, 1)); + redefineImage(level, getBaseLevelInternalFormat(), levelSize); + } +} + +gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + // ensure the underlying texture is created + ANGLE_TRY(ensureRenderTarget()); + + if (index.hasLayer()) + { + ANGLE_TRY(updateStorage()); + } + else + { + ANGLE_TRY(updateStorageLevel(index.mipIndex)); + } + + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(getBaseLevel())) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); + + TextureStorage *storage = NULL; + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + ANGLE_TRY(updateStorage()); + + return gl::NoError(); +} + +gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +{ + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLevelZeroDepth(); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); + + // TODO: Verify creation of the storage succeeded + *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 3D storage, as that is D3D9/ES2-only + ASSERT(!mTexStorage->isManaged()); + + return gl::NoError(); +} + +gl::Error TextureD3D_3D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + } + } + + return gl::NoError(); +} + +bool TextureD3D_3D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_3D::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLevelZeroDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + if (level == static_cast<int>(getBaseLevel())) + { + return true; + } + + ImageD3D *levelImage = mImageArray[level]; + + if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (levelImage->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (levelImage->getHeight() != std::max(1, height >> level)) + { + return false; + } + + if (levelImage->getDepth() != std::max(1, depth >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_3D::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + ANGLE_TRY(commitRegion(index, region)); + } + + return gl::NoError(); +} + +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getLevelZeroWidth() >> level); + const int storageHeight = std::max(1, getLevelZeroHeight() >> level); + const int storageDepth = std::max(1, getLevelZeroDepth() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + markAllImagesDirty(); + SafeDelete(mTexStorage); + } + } +} + +gl::ImageIndexIterator TextureD3D_3D::imageIterator() const +{ + return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(), + gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL); +} + +gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // The "layer" here does not apply to 3D images. We use one Image per mip. + return gl::ImageIndex::Make3D(mip); +} + +bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_3D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +void TextureD3D_3D::markAllImagesDirty() +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + mDirtyImages = true; +} + +GLint TextureD3D_3D::getLevelZeroDepth() const +{ + ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelDepth())) > getBaseLevel()); + return getBaseLevelDepth() << getBaseLevel(); +} + +TextureD3D_2DArray::TextureD3D_2DArray(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + mLayerCounts[level] = 0; + mImageArray[level] = NULL; + } +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + deleteImages(); + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT((layer == 0 && mLayerCounts[level] == 0) || + layer < mLayerCounts[level]); + return (mImageArray[level] ? mImageArray[level][layer] : NULL); +} + +ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) || + index.layerIndex < mLayerCounts[index.mipIndex]); + ASSERT(index.type == GL_TEXTURE_2D_ARRAY); + return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL); +} + +GLsizei TextureD3D_2DArray::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mLayerCounts[level]; +} + +GLsizei TextureD3D_2DArray::getWidth(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; +} + +GLsizei TextureD3D_2DArray::getHeight(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; +} + +GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; +} + +bool TextureD3D_2DArray::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_2DArray::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLint level = static_cast<GLint>(imageLevel); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + redefineImage(level, sizedInternalFormat, size); + + const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(size.width, size.height, unpack.alignment, + unpack.rowLength, unpack.imageHeight), + inputDepthPitch); + + for (int i = 0; i < size.depth; i++) + { + const ptrdiff_t layerOffset = (inputDepthPitch * i); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + GLint level = static_cast<GLint>(imageLevel); + const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(area.width, area.height, unpack.alignment, + unpack.rowLength, unpack.imageHeight), + inputDepthPitch); + + for (int i = 0; i < area.depth; i++) + { + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + ANGLE_TRY( + TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLint level = static_cast<GLint>(imageLevel); + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeDepthPitch(size.width, size.height, 1, 0, 0), + inputDepthPitch); + + for (int i = 0; i < size.depth; i++) + { + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeDepthPitch(area.width, area.height, 1, 0, 0), + inputDepthPitch); + + for (int i = 0; i < area.depth; i++) + { + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer); + ANGLE_TRY( + TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset)); + ANGLE_TRY(commitRegion(index, layerArea)); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); +} + +gl::Error TextureD3D_2DArray::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLint level = static_cast<GLint>(imageLevel); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + + if (canCreateRenderTargetForImage(index)) + { + gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0); + ANGLE_TRY(mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, sourceArea, + source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget()); + + if (isValidLevel(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + ANGLE_TRY(mRenderer->copyImage2DArray( + source, sourceArea, + gl::GetInternalFormatInfo(getInternalFormat(getBaseLevel())).format, destOffset, + mTexStorage, level)); + } + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + deleteImages(); + + for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + gl::Extents levelLayerSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); + + mLayerCounts[level] = (level < levels ? size.depth : 0); + + if (mLayerCounts[level] > 0) + { + // Create new images for this level + mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = mRenderer->createImage(); + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true); + } + } + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TextureStorage *storage = + mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, + size.height, size.depth, static_cast<int>(levels)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ANGLE_TRY(updateStorage()); + + mImmutable = true; + + return gl::NoError(); +} + +void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_2DArray::releaseTexImage() +{ + UNREACHABLE(); +} + +void TextureD3D_2DArray::initMipmapImages() +{ + const GLuint baseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + int baseWidth = getLevelZeroWidth(); + int baseHeight = getLevelZeroHeight(); + int baseDepth = getLayerCount(getBaseLevel()); + GLenum baseFormat = getBaseLevelInternalFormat(); + + // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap + // levels. + for (GLuint level = baseLevel + 1u; level <= maxLevel; level++) + { + ASSERT((baseWidth >> level) > 0 || (baseHeight >> level) > 0); + gl::Extents levelLayerSize(std::max(baseWidth >> level, 1), + std::max(baseHeight >> level, 1), + baseDepth); + redefineImage(level, baseFormat, levelLayerSize); + } +} + +gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + // ensure the underlying texture is created + ANGLE_TRY(ensureRenderTarget()); + ANGLE_TRY(updateStorageLevel(index.mipIndex)); + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::NoError(); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(getBaseLevel())) + { + return gl::NoError(); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); + + TextureStorage *storage = nullptr; + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + ANGLE_TRY(updateStorage()); + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +{ + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLayerCount(getBaseLevel()); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + // TODO(geofflang): Verify storage creation succeeds + *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only + ASSERT(!mTexStorage->isManaged()); + + return gl::NoError(); +} + +gl::Error TextureD3D_2DArray::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (isLevelComplete(level)) + { + ANGLE_TRY(updateStorageLevel(level)); + } + } + + return gl::NoError(); +} + +bool TextureD3D_2DArray::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_2DArray::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // Layers check needs to happen after the above checks, otherwise out-of-range base level may be + // queried. + GLsizei layers = getLayerCount(getBaseLevel()); + + if (layers <= 0) + { + return false; + } + + if (level == static_cast<int>(getBaseLevel())) + { + return true; + } + + if (getInternalFormat(level) != getInternalFormat(getBaseLevel())) + { + return false; + } + + if (getWidth(level) != std::max(1, width >> level)) + { + return false; + } + + if (getHeight(level) != std::max(1, height >> level)) + { + return false; + } + + if (getLayerCount(level) != layers) + { + return false; + } + + return true; +} + +bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_2DArray::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(isLevelComplete(level)); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + if (mImageArray[level][layer]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + ANGLE_TRY(commitRegion(index, region)); + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2DArray::deleteImages() +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + for (int layer = 0; layer < mLayerCounts[level]; ++layer) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = 0; + } +} + +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getLevelZeroWidth() >> level); + const int storageHeight = std::max(1, getLevelZeroHeight() >> level); + const GLuint baseLevel = getBaseLevel(); + int storageDepth = 0; + if (baseLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + storageDepth = getLayerCount(baseLevel); + } + + // Only reallocate the layers if the size doesn't match + if (size.depth != mLayerCounts[level]) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + SafeDelete(mImageArray[level][layer]); + } + SafeDeleteArray(mImageArray[level]); + mLayerCounts[level] = size.depth; + + if (size.depth > 0) + { + mImageArray[level] = new ImageD3D*[size.depth]; + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = mRenderer->createImage(); + } + } + } + + if (size.depth > 0) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat, + gl::Extents(size.width, size.height, 1), false); + } + } + + if (mTexStorage) + { + const GLenum storageFormat = getBaseLevelInternalFormat(); + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + markAllImagesDirty(); + SafeDelete(mTexStorage); + } + } +} + +gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const +{ + return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts); +} + +gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const +{ + return gl::ImageIndex::Make2DArray(mip, layer); +} + +bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const +{ + // Check for having a storage and the right type of index + if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY) + { + return false; + } + + // Check the mip index + if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount()) + { + return false; + } + + // Check the layer index + return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex])); +} + +void TextureD3D_2DArray::markAllImagesDirty() +{ + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) + { + for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++) + { + mImageArray[dirtyLevel][dirtyLayer]->markDirty(); + } + } + mDirtyImages = true; +} + +TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) +{ +} + +TextureD3D_External::~TextureD3D_External() +{ + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const +{ + UNREACHABLE(); + return nullptr; +} + +GLsizei TextureD3D_External::getLayerCount(int level) const +{ + return 1; +} + +gl::Error TextureD3D_External::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + // Image setting is not supported for external images + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::setCompressedSubImage(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::copyImage(GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::setStorage(GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_External::setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + ASSERT(target == GL_TEXTURE_EXTERNAL_OES); + + SafeDelete(mTexStorage); + + // If the stream is null, the external image is unbound and we release the storage + if (stream != nullptr) + { + mTexStorage = mRenderer->createTextureStorageExternal(stream, desc); + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_External::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_External::releaseTexImage() +{ + UNREACHABLE(); +} + +gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image) +{ + EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image); + + // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error. + RenderTargetD3D *renderTargetD3D = nullptr; + ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D)); + + SafeDelete(mTexStorage); + mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D); + + return gl::NoError(); +} + +void TextureD3D_External::initMipmapImages() +{ + UNREACHABLE(); +} + +gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const +{ + return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false; +} + +gl::Error TextureD3D_External::initializeStorage(bool renderTarget) +{ + // Texture storage is created when an external image is bound + ASSERT(mTexStorage); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget, + TextureStorage **outTexStorage) const +{ + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_External::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_External::updateStorage() +{ + // Texture storage does not need to be updated since it is already loaded with the latest + // external image + ASSERT(mTexStorage); + return gl::Error(GL_NO_ERROR); +} + +gl::ImageIndexIterator TextureD3D_External::imageIterator() const +{ + return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); +} + +gl::ImageIndex TextureD3D_External::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // "layer" does not apply to 2D Textures. + return gl::ImageIndex::Make2D(mip); +} + +bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_EXTERNAL_OES && index.mipIndex == 0); +} + +void TextureD3D_External::markAllImagesDirty() +{ + UNREACHABLE(); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h new file mode 100755 index 000000000..99343632a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h @@ -0,0 +1,505 @@ +// +// Copyright 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. +// + +// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ + +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Stream.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class EGLImageD3D; +class ImageD3D; +class RendererD3D; +class RenderTargetD3D; +class TextureStorage; + +class TextureD3D : public TextureImpl +{ + public: + TextureD3D(const gl::TextureState &data, RendererD3D *renderer); + virtual ~TextureD3D(); + + gl::Error getNativeTexture(TextureStorage **outStorage); + + bool hasDirtyImages() const { return mDirtyImages; } + void resetDirty() { mDirtyImages = false; } + + virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0; + virtual GLsizei getLayerCount(int level) const = 0; + + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLenum getBaseLevelInternalFormat() const; + + bool isImmutable() const { return mImmutable; } + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + + // Returns an iterator over all "Images" for this particular Texture. + virtual gl::ImageIndexIterator imageIterator() const = 0; + + // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for + // slices of their depth texures, so 3D textures ignore the layer parameter. + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; + virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; + + virtual gl::Error setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + gl::Error generateMipmap() override; + TextureStorage *getStorage(); + ImageD3D *getBaseLevelImage() const; + + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; + + void setBaseLevel(GLuint baseLevel) override; + + void syncState(const gl::Texture::DirtyBits &dirtyBits) override; + + protected: + gl::Error setImageImpl(const gl::ImageIndex &index, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset); + gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error setCompressedImageImpl(const gl::ImageIndex &index, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset); + gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); + bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); + gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget); + + GLint getLevelZeroWidth() const; + GLint getLevelZeroHeight() const; + virtual GLint getLevelZeroDepth() const; + + GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; + virtual void initMipmapImages() = 0; + bool isBaseImageZeroSize() const; + virtual bool isImageComplete(const gl::ImageIndex &index) const = 0; + + bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const; + virtual gl::Error ensureRenderTarget(); + + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0; + gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box ®ion); + + GLuint getBaseLevel() const { return mBaseLevel; }; + + virtual void markAllImagesDirty() = 0; + + GLint getBaseLevelDepth() const; + + RendererD3D *mRenderer; + + bool mDirtyImages; + + bool mImmutable; + TextureStorage *mTexStorage; + + private: + virtual gl::Error initializeStorage(bool renderTarget) = 0; + + virtual gl::Error updateStorage() = 0; + + bool shouldUseSetData(const ImageD3D *image) const; + + gl::Error generateMipmapUsingImages(const GLuint maxLevel); + + GLuint mBaseLevel; +}; + +class TextureD3D_2D : public TextureD3D +{ + public: + TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer); + virtual ~TextureD3D_2D(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error copyTexture(GLenum internalFormat, + GLenum type, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + gl::Error copySubTexture(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + gl::Error copyCompressedTexture(const gl::Texture *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + protected: + void markAllImagesDirty() override; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + virtual void initMipmapImages(); + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + + gl::Error updateStorageLevel(int level); + + void redefineImage(size_t level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); + + bool mEGLImageTarget; + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_Cube : public TextureD3D +{ + public: + TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer); + virtual ~TextureD3D_Cube(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty() { mDirtyImages = false; } + + GLenum getInternalFormat(GLint level, GLint layer) const; + bool isDepth(GLint level, GLint layer) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + protected: + void markAllImagesDirty() override; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + void initMipmapImages() override; + + bool isValidFaceLevel(int faceIndex, int level) const; + bool isFaceLevelComplete(int faceIndex, int level) const; + bool isCubeComplete() const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageFaceLevel(int faceIndex, int level); + + void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size); + + ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_3D : public TextureD3D +{ + public: + TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer); + virtual ~TextureD3D_3D(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + protected: + void markAllImagesDirty() override; + GLint getLevelZeroDepth() const override; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + void initMipmapImages() override; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_2DArray : public TextureD3D +{ + public: + TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer); + virtual ~TextureD3D_2DArray(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + protected: + void markAllImagesDirty() override; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + void initMipmapImages() override; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); + + void deleteImages(); + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + + // Storing images as an array of single depth textures since D3D11 treats each array level of a + // Texture2D object as a separate subresource. Each layer would have to be looped over + // to update all the texture layers since they cannot all be updated at once and it makes the most + // sense for the Image class to not have to worry about layer subresource as well as mip subresources. + GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_External : public TextureD3D +{ + public: + TextureD3D_External(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_External() override; + + ImageD3D *getImage(const gl::ImageIndex &index) const override; + GLsizei getLayerCount(int level) const override; + + gl::Error setImage(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + + void bindTexImage(egl::Surface *surface) override; + void releaseTexImage() override; + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + + gl::ImageIndexIterator imageIterator() const override; + gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override; + bool isValidIndex(const gl::ImageIndex &index) const override; + + protected: + void markAllImagesDirty() override; + + private: + gl::Error initializeStorage(bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TextureStorage **outTexStorage) const override; + gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override; + + gl::Error updateStorage() override; + void initMipmapImages() override; + + bool isImageComplete(const gl::ImageIndex &index) const override; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h new file mode 100755 index 000000000..417237495 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2002-2013 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. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorage class. + +#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ + +#include "libANGLE/Error.h" + +#include "common/debug.h" +#include "libANGLE/Error.h" + +#include <GLES2/gl2.h> +#include <stdint.h> + +namespace gl +{ +struct ImageIndex; +struct Box; +struct PixelUnpackState; +} + +namespace rx +{ +class SwapChainD3D; +class RenderTargetD3D; +class ImageD3D; + +class TextureStorage : angle::NonCopyable +{ + public: + TextureStorage() {} + virtual ~TextureStorage() {} + + virtual int getTopLevel() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual bool supportsNativeMipmapFunction() const = 0; + virtual int getLevelCount() const = 0; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0; + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; + + // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it. + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); } +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp new file mode 100755 index 000000000..eea85fea7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp @@ -0,0 +1,405 @@ +// +// Copyright 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. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers in D3D +// for linking between shader stages. +// + +#include "libANGLE/renderer/d3d/VaryingPacking.h" + +#include "common/utilities.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" + +namespace rx +{ + +// Implementation of VaryingPacking::BuiltinVarying +VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false) +{ +} + +std::string VaryingPacking::BuiltinVarying::str() const +{ + return (systemValue ? semantic : (semantic + Str(index))); +} + +void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic) +{ + enabled = true; + semantic = systemValueSemantic; + systemValue = true; +} + +void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal) +{ + enabled = true; + semantic = semanticVal; + index = indexVal; +} + +// Implementation of VaryingPacking +VaryingPacking::VaryingPacking(GLuint maxVaryingVectors) + : mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX) +{ +} + +// Packs varyings into generic varying registers, using the algorithm from +// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 +// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119 +// Returns false if unsuccessful. +bool VaryingPacking::packVarying(const PackedVarying &packedVarying) +{ + unsigned int varyingRows = 0; + unsigned int varyingColumns = 0; + + const auto &varying = *packedVarying.varying; + + // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN + // where N is the greater of C and R.Variables of type mat2 occupies 2 complete rows." + // Here we are a bit more conservative and allow packing non-square matrices more tightly. + // Make sure we use transposed matrix types to count registers correctly. + ASSERT(!varying.isStruct()); + GLenum transposedType = gl::TransposeMatrixType(varying.type); + varyingRows = gl::VariableRowCount(transposedType); + varyingColumns = gl::VariableColumnCount(transposedType); + + // "Arrays of size N are assumed to take N times the size of the base type" + varyingRows *= varying.elementCount(); + + unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size()); + + if (varyingRows > maxVaryingVectors) { + return false; + } + + // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row. + // Variables are then allocated to successive rows, aligning them to the 1st column." + if (varyingColumns >= 2 && varyingColumns <= 4) + { + for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row) + { + if (isFree(row, 0, varyingRows, varyingColumns)) + { + insert(row, 0, packedVarying); + return true; + } + } + + // "For 2 component variables, when there are no spare rows, the strategy is switched to + // using the highest numbered row and the lowest numbered column where the variable will + // fit." + if (varyingColumns == 2) + { + for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;) + { + if (isFree(r, 2, varyingRows, 2)) + { + insert(r, 2, packedVarying); + return true; + } + } + } + + return false; + } + + // "1 component variables have their own packing rule. They are packed in order of size, largest + // first. Each variable is placed in the column that leaves the least amount of space in the + // column and aligned to the lowest available rows within that column." + ASSERT(varyingColumns == 1); + unsigned int contiguousSpace[4] = {0}; + unsigned int bestContiguousSpace[4] = {0}; + unsigned int totalSpace[4] = {0}; + + for (unsigned int row = 0; row < maxVaryingVectors; ++row) + { + for (unsigned int column = 0; column < 4; ++column) + { + if (mRegisterMap[row][column]) + { + contiguousSpace[column] = 0; + } + else + { + contiguousSpace[column]++; + totalSpace[column]++; + + if (contiguousSpace[column] > bestContiguousSpace[column]) + { + bestContiguousSpace[column] = contiguousSpace[column]; + } + } + } + } + + unsigned int bestColumn = 0; + for (unsigned int column = 1; column < 4; ++column) + { + if (bestContiguousSpace[column] >= varyingRows && + (bestContiguousSpace[bestColumn] < varyingRows || + totalSpace[column] < totalSpace[bestColumn])) + { + bestColumn = column; + } + } + + if (bestContiguousSpace[bestColumn] >= varyingRows) + { + for (unsigned int row = 0; row < maxVaryingVectors; row++) + { + if (isFree(row, bestColumn, varyingRows, 1)) + { + for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex) + { + // If varyingRows > 1, it must be an array. + PackedVaryingRegister registerInfo; + registerInfo.packedVarying = &packedVarying; + registerInfo.registerRow = row + arrayIndex; + registerInfo.registerColumn = bestColumn; + registerInfo.varyingArrayIndex = arrayIndex; + registerInfo.varyingRowIndex = 0; + mRegisterList.push_back(registerInfo); + mRegisterMap[row + arrayIndex][bestColumn] = true; + } + break; + } + } + return true; + } + + return false; +} + +bool VaryingPacking::isFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const +{ + for (unsigned int row = 0; row < varyingRows; ++row) + { + ASSERT(registerRow + row < mRegisterMap.size()); + for (unsigned int column = 0; column < varyingColumns; ++column) + { + ASSERT(registerColumn + column < 4); + if (mRegisterMap[registerRow + row][registerColumn + column]) + { + return false; + } + } + } + + return true; +} + +void VaryingPacking::insert(unsigned int registerRow, + unsigned int registerColumn, + const PackedVarying &packedVarying) +{ + unsigned int varyingRows = 0; + unsigned int varyingColumns = 0; + + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isStruct()); + GLenum transposedType = gl::TransposeMatrixType(varying.type); + varyingRows = gl::VariableRowCount(transposedType); + varyingColumns = gl::VariableColumnCount(transposedType); + + PackedVaryingRegister registerInfo; + registerInfo.packedVarying = &packedVarying; + registerInfo.registerColumn = registerColumn; + + for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement) + { + for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow) + { + registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow; + registerInfo.varyingRowIndex = varyingRow; + registerInfo.varyingArrayIndex = arrayElement; + mRegisterList.push_back(registerInfo); + + for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex) + { + mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true; + } + } + } +} + +// See comment on packVarying. +bool VaryingPacking::packVaryings(gl::InfoLog &infoLog, + const std::vector<PackedVarying> &packedVaryings, + const std::vector<std::string> &transformFeedbackVaryings) +{ + std::set<std::string> uniqueVaryingNames; + + // "Variables are packed into the registers one at a time so that they each occupy a contiguous + // subrectangle. No splitting of variables is permitted." + for (const PackedVarying &packedVarying : packedVaryings) + { + const auto &varying = *packedVarying.varying; + + // Do not assign registers to built-in or unreferenced varyings + if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField())) + { + continue; + } + + ASSERT(!varying.isStruct()); + ASSERT(uniqueVaryingNames.count(varying.name) == 0); + + if (packVarying(packedVarying)) + { + uniqueVaryingNames.insert(varying.name); + } + else + { + infoLog << "Could not pack varying " << varying.name; + return false; + } + } + + for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings) + { + if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0) + { + // do not pack builtin XFB varyings + continue; + } + + bool found = false; + for (const PackedVarying &packedVarying : packedVaryings) + { + const auto &varying = *packedVarying.varying; + + // Make sure transform feedback varyings aren't optimized out. + if (uniqueVaryingNames.count(transformFeedbackVaryingName) > 0) + { + found = true; + break; + } + + if (transformFeedbackVaryingName == varying.name) + { + if (!packVarying(packedVarying)) + { + infoLog << "Could not pack varying " << varying.name; + return false; + } + + found = true; + break; + } + } + + if (!found) + { + infoLog << "Transform feedback varying " << transformFeedbackVaryingName + << " does not exist in the vertex shader."; + return false; + } + } + + // Sort the packed register list + std::sort(mRegisterList.begin(), mRegisterList.end()); + + // Assign semantic indices + for (unsigned int semanticIndex = 0; + semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex) + { + mRegisterList[semanticIndex].semanticIndex = semanticIndex; + } + + return true; +} + +unsigned int VaryingPacking::getRegisterCount() const +{ + unsigned int count = 0; + + for (const Register ® : mRegisterMap) + { + if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3]) + { + ++count; + } + } + + if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled) + { + ++count; + } + + if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled) + { + ++count; + } + + return count; +} + +void VaryingPacking::enableBuiltins(ShaderType shaderType, + const ProgramD3DMetadata &programMetadata) +{ + int majorShaderModel = programMetadata.getRendererMajorShaderModel(); + bool position = programMetadata.usesTransformFeedbackGLPosition(); + bool fragCoord = programMetadata.usesFragCoord(); + bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader() + : programMetadata.usesPointCoord(); + bool pointSize = programMetadata.usesSystemValuePointSize(); + bool hlsl4 = (majorShaderModel >= 4); + const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize); + + unsigned int reservedSemanticIndex = getMaxSemanticIndex(); + + BuiltinInfo *builtins = &mBuiltinInfo[shaderType]; + + if (hlsl4) + { + builtins->dxPosition.enableSystem("SV_Position"); + } + else if (shaderType == SHADER_PIXEL) + { + builtins->dxPosition.enableSystem("VPOS"); + } + else + { + builtins->dxPosition.enableSystem("POSITION"); + } + + if (position) + { + builtins->glPosition.enable(userSemantic, reservedSemanticIndex++); + } + + if (fragCoord) + { + builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++); + } + + if (pointCoord) + { + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + if (hlsl4) + { + builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++); + } + else + { + builtins->glPointCoord.enable("TEXCOORD", 0); + } + } + + // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders + if (pointSize && (shaderType != SHADER_PIXEL || hlsl4)) + { + builtins->glPointSize.enableSystem("PSIZE"); + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h new file mode 100755 index 000000000..ca4640b00 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h @@ -0,0 +1,175 @@ +// +// Copyright 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. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers in D3D +// for linking between shader stages. +// + +#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ +#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ +class ProgramD3DMetadata; + +struct PackedVarying +{ + PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn) + : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn) + { + } + PackedVarying(const sh::ShaderVariable &varyingIn, + sh::InterpolationType interpolationIn, + const std::string &parentStructNameIn) + : varying(&varyingIn), + vertexOnly(false), + interpolation(interpolationIn), + parentStructName(parentStructNameIn) + { + } + + bool isStructField() const { return !parentStructName.empty(); } + + const sh::ShaderVariable *varying; + + // Transform feedback varyings can be only referenced in the VS. + bool vertexOnly; + + // Cached so we can store sh::ShaderVariable to point to varying fields. + sh::InterpolationType interpolation; + + // Struct name + std::string parentStructName; +}; + +struct PackedVaryingRegister final +{ + PackedVaryingRegister() + : packedVarying(nullptr), + varyingArrayIndex(0), + varyingRowIndex(0), + registerRow(0), + registerColumn(0) + { + } + + PackedVaryingRegister(const PackedVaryingRegister &) = default; + PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; + + bool operator<(const PackedVaryingRegister &other) const + { + return sortOrder() < other.sortOrder(); + } + + unsigned int sortOrder() const + { + // TODO(jmadill): Handle interpolation types + return registerRow * 4 + registerColumn; + } + + bool isStructField() const { return !structFieldName.empty(); } + + // Index to the array of varyings. + const PackedVarying *packedVarying; + + // The array element of the packed varying. + unsigned int varyingArrayIndex; + + // The row of the array element of the packed varying. + unsigned int varyingRowIndex; + + // The register row to which we've assigned this packed varying. + unsigned int registerRow; + + // The column of the register row into which we've packed this varying. + unsigned int registerColumn; + + // Assigned after packing + unsigned int semanticIndex; + + // Struct member this varying corresponds to. + std::string structFieldName; +}; + +class VaryingPacking final : angle::NonCopyable +{ + public: + VaryingPacking(GLuint maxVaryingVectors); + + bool packVaryings(gl::InfoLog &infoLog, + const std::vector<PackedVarying> &packedVaryings, + const std::vector<std::string> &transformFeedbackVaryings); + + struct Register + { + Register() { data[0] = data[1] = data[2] = data[3] = false; } + + bool &operator[](unsigned int index) { return data[index]; } + bool operator[](unsigned int index) const { return data[index]; } + + bool data[4]; + }; + + Register &operator[](unsigned int index) { return mRegisterMap[index]; } + const Register &operator[](unsigned int index) const { return mRegisterMap[index]; } + + const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; } + unsigned int getMaxSemanticIndex() const + { + return static_cast<unsigned int>(mRegisterList.size()); + } + unsigned int getRegisterCount() const; + + void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata); + + struct BuiltinVarying final : angle::NonCopyable + { + BuiltinVarying(); + + std::string str() const; + void enableSystem(const std::string &systemValueSemantic); + void enable(const std::string &semanticVal, unsigned int indexVal); + + bool enabled; + std::string semantic; + unsigned int index; + bool systemValue; + }; + + struct BuiltinInfo + { + BuiltinVarying dxPosition; + BuiltinVarying glPosition; + BuiltinVarying glFragCoord; + BuiltinVarying glPointCoord; + BuiltinVarying glPointSize; + }; + + const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; } + + bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; } + + private: + bool packVarying(const PackedVarying &packedVarying); + bool isFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const; + void insert(unsigned int registerRow, + unsigned int registerColumn, + const PackedVarying &packedVarying); + + std::vector<Register> mRegisterMap; + std::vector<PackedVaryingRegister> mRegisterList; + + std::vector<BuiltinInfo> mBuiltinInfo; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp new file mode 100755 index 000000000..ac31a865e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -0,0 +1,280 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +#include "common/mathutil.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/VertexAttribute.h" + +namespace rx +{ + +// VertexBuffer Implementation +unsigned int VertexBuffer::mNextSerial = 1; + +VertexBuffer::VertexBuffer() : mRefCount(1) +{ + updateSerial(); +} + +VertexBuffer::~VertexBuffer() +{ +} + +void VertexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + +unsigned int VertexBuffer::getSerial() const +{ + return mSerial; +} + +void VertexBuffer::addRef() +{ + mRefCount++; +} + +void VertexBuffer::release() +{ + ASSERT(mRefCount > 0); + mRefCount--; + + if (mRefCount == 0) + { + delete this; + } +} + +// VertexBufferInterface Implementation +VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic) + : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic) +{ +} + +VertexBufferInterface::~VertexBufferInterface() +{ + if (mVertexBuffer) + { + mVertexBuffer->release(); + } +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +gl::Error VertexBufferInterface::setBufferSize(unsigned int size) +{ + if (mVertexBuffer->getBufferSize() == 0) + { + return mVertexBuffer->initialize(size, mDynamic); + } + + return mVertexBuffer->setBufferSize(size); +} + +gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired( + const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const +{ + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, count, instances), spaceRequired); + + // Align to 16-byte boundary + unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u); + + if (alignedSpaceRequired < spaceRequired) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired."); + } + + return alignedSpaceRequired; +} + +gl::Error VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +VertexBuffer *VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + +// StreamingVertexBufferInterface Implementation +StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, + std::size_t initialSize) + : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0) +{ + setBufferSize(static_cast<unsigned int>(initialSize)); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + ANGLE_TRY(setBufferSize(std::max(size, 3 * curBufferSize / 2))); + mWritePosition = 0; + } + else if (mWritePosition + size > curBufferSize) + { + ANGLE_TRY(discard()); + mWritePosition = 0; + } + + return gl::NoError(); +} + +gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData) +{ + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(getSpaceRequired(attrib, count, instances), spaceRequired); + + // Protect against integer overflow + angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition); + checkedPosition += spaceRequired; + if (!checkedPosition.IsValid()) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow."); + } + + ANGLE_TRY(reserveSpace(mReservedSpace)); + mReservedSpace = 0; + + ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count, + instances, mWritePosition, sourceData)); + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; + + return gl::NoError(); +} + +gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) +{ + unsigned int requiredSpace = 0; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, count, instances), requiredSpace); + + // Align to 16-byte boundary + auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u); + alignedRequiredSpace += mReservedSpace; + + // Protect against integer overflow + if (!alignedRequiredSpace.IsValid()) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Unable to reserve %u extra bytes in internal vertex buffer, " + "it would result in an overflow.", + requiredSpace); + } + + mReservedSpace = alignedRequiredSpace.ValueOrDie(); + + return gl::NoError(); +} + +// StaticVertexBufferInterface Implementation +StaticVertexBufferInterface::AttributeSignature::AttributeSignature() + : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0) +{ +} + +bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute( + const gl::VertexAttribute &attrib) const +{ + size_t attribStride = ComputeVertexAttributeStride(attrib); + + if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride || + normalized != attrib.normalized || pureInteger != attrib.pureInteger) + { + return false; + } + + size_t attribOffset = (static_cast<size_t>(attrib.offset) % attribStride); + return (offset == attribOffset); +} + +void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib) +{ + type = attrib.type; + size = attrib.size; + normalized = attrib.normalized; + pureInteger = attrib.pureInteger; + offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib)); + offset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib); +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) + : VertexBufferInterface(factory, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib) const +{ + return mSignature.matchesAttribute(attrib); +} + +void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib) +{ + return mSignature.set(attrib); +} + +gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib, + GLint start, + GLsizei count, + GLsizei instances, + const uint8_t *sourceData) +{ + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(getSpaceRequired(attrib, count, instances), spaceRequired); + setBufferSize(spaceRequired); + + ASSERT(attrib.enabled); + ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, GL_NONE, start, count, instances, 0, + sourceData)); + + mSignature.set(attrib); + mVertexBuffer->hintUnmapResource(); + return gl::NoError(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h new file mode 100755 index 000000000..b3d98247f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -0,0 +1,159 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#ifndef LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#include <GLES2/gl2.h> + +#include <cstddef> +#include <cstdint> +#include <vector> + +namespace gl +{ +struct VertexAttribute; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class BufferFactoryD3D; + +// Use a ref-counting scheme with self-deletion on release. We do this so that we can more +// easily manage the static buffer cache, without deleting currently bound buffers. +class VertexBuffer : angle::NonCopyable +{ + public: + VertexBuffer(); + + virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; + + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) = 0; + + virtual unsigned int getBufferSize() const = 0; + virtual gl::Error setBufferSize(unsigned int size) = 0; + virtual gl::Error discard() = 0; + + unsigned int getSerial() const; + + // This may be overridden (e.g. by VertexBuffer11) if necessary. + virtual void hintUnmapResource() { }; + + // Reference counting. + void addRef(); + void release(); + + protected: + void updateSerial(); + virtual ~VertexBuffer(); + + private: + unsigned int mSerial; + static unsigned int mNextSerial; + unsigned int mRefCount; +}; + +class VertexBufferInterface : angle::NonCopyable +{ + public: + VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic); + virtual ~VertexBufferInterface(); + + unsigned int getBufferSize() const; + bool empty() const { return getBufferSize() == 0; } + + unsigned int getSerial() const; + + VertexBuffer *getVertexBuffer() const; + + protected: + gl::Error discard(); + + gl::Error setBufferSize(unsigned int size); + gl::ErrorOrResult<unsigned int> getSpaceRequired(const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const; + BufferFactoryD3D *const mFactory; + VertexBuffer *mVertexBuffer; + bool mDynamic; +}; + +class StreamingVertexBufferInterface : public VertexBufferInterface +{ + public: + StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize); + ~StreamingVertexBufferInterface(); + + gl::Error storeDynamicAttribute(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData); + + gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, + GLsizei count, + GLsizei instances); + + private: + gl::Error reserveSpace(unsigned int size); + + unsigned int mWritePosition; + unsigned int mReservedSpace; +}; + +class StaticVertexBufferInterface : public VertexBufferInterface +{ + public: + explicit StaticVertexBufferInterface(BufferFactoryD3D *factory); + ~StaticVertexBufferInterface(); + + gl::Error storeStaticAttribute(const gl::VertexAttribute &attrib, + GLint start, + GLsizei count, + GLsizei instances, + const uint8_t *sourceData); + + bool matchesAttribute(const gl::VertexAttribute &attribute) const; + void setAttribute(const gl::VertexAttribute &attribute); + + private: + class AttributeSignature final : angle::NonCopyable + { + public: + AttributeSignature(); + bool matchesAttribute(const gl::VertexAttribute &attrib) const; + void set(const gl::VertexAttribute &attrib); + + private: + GLenum type; + GLuint size; + GLuint stride; + bool normalized; + bool pureInteger; + size_t offset; + }; + + AttributeSignature mSignature; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp new file mode 100755 index 000000000..89dd4faf2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -0,0 +1,589 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +#include "common/BitSetIterator.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +using namespace angle; + +namespace rx +{ +namespace +{ +enum +{ + INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024 +}; +// This has to be at least 4k or else it fails on ATI cards. +enum +{ + CONSTANT_VERTEX_BUFFER_SIZE = 4096 +}; + +int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size) +{ + // Size cannot be larger than a GLsizei + if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) + { + size = static_cast<unsigned int>(std::numeric_limits<int>::max()); + } + + GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib)); + return (size - attrib.offset % stride + + (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) / + stride; +} + +bool DirectStoragePossible(const gl::VertexAttribute &attrib) +{ + // Current value attribs may not use direct storage. + if (!attrib.enabled) + { + return false; + } + + gl::Buffer *buffer = attrib.buffer.get(); + if (!buffer) + { + return false; + } + + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + ASSERT(bufferD3D); + if (!bufferD3D->supportsDirectBinding()) + { + return false; + } + + // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a + // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed) + size_t alignment = 4; + + if (attrib.type != GL_FLOAT) + { + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib); + + // TODO(jmadill): add VertexFormatCaps + BufferFactoryD3D *factory = bufferD3D->getFactory(); + + auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, 1, 0); + if (errorOrElementSize.isError()) + { + ERR("Unlogged error in DirectStoragePossible."); + return false; + } + + alignment = std::min<size_t>(errorOrElementSize.getResult(), 4); + + // CPU-converted vertex data must be converted (naturally). + if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0) + { + return false; + } + } + + // Final alignment check - unaligned data must be converted. + return (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) && + (static_cast<size_t>(attrib.offset) % alignment == 0); +} +} // anonymous namespace + +TranslatedAttribute::TranslatedAttribute() + : active(false), + attribute(nullptr), + currentValueType(GL_NONE), + baseOffset(0), + usesFirstVertexOffset(false), + stride(0), + vertexBuffer(), + storage(nullptr), + serial(0), + divisor(0) +{ +} + +gl::ErrorOrResult<unsigned int> TranslatedAttribute::computeOffset(GLint startVertex) const +{ + if (!usesFirstVertexOffset) + { + return baseOffset; + } + + CheckedNumeric<unsigned int> offset; + + offset = baseOffset + stride * static_cast<unsigned int>(startVertex); + ANGLE_TRY_CHECKED_MATH(offset); + return offset.ValueOrDie(); +} + +VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib) +{ + // If attribute is disabled, we use the current value. + if (!attrib.enabled) + { + return VertexStorageType::CURRENT_VALUE; + } + + // If specified with immediate data, we must use dynamic storage. + auto *buffer = attrib.buffer.get(); + if (!buffer) + { + return VertexStorageType::DYNAMIC; + } + + // Check if the buffer supports direct storage. + if (DirectStoragePossible(attrib)) + { + return VertexStorageType::DIRECT; + } + + // Otherwise the storage is static or dynamic. + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + ASSERT(bufferD3D); + switch (bufferD3D->getUsage()) + { + case D3DBufferUsage::DYNAMIC: + return VertexStorageType::DYNAMIC; + case D3DBufferUsage::STATIC: + return VertexStorageType::STATIC; + default: + UNREACHABLE(); + return VertexStorageType::UNKNOWN; + } +} + +VertexDataManager::CurrentValueState::CurrentValueState() + : buffer(nullptr), + offset(0) +{ + data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN(); + data.Type = GL_FLOAT; +} + +VertexDataManager::CurrentValueState::~CurrentValueState() +{ + SafeDelete(buffer); +} + +VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) + : mFactory(factory), + mStreamingBuffer(nullptr), + // TODO(jmadill): use context caps + mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS) +{ + mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE); + + if (!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + SafeDelete(mStreamingBuffer); +} + +gl::Error VertexDataManager::prepareVertexData(const gl::State &state, + GLint start, + GLsizei count, + std::vector<TranslatedAttribute> *translatedAttribs, + GLsizei instances) +{ + ASSERT(mStreamingBuffer); + + const gl::VertexArray *vertexArray = state.getVertexArray(); + const auto &vertexAttributes = vertexArray->getVertexAttributes(); + + mDynamicAttribsMaskCache.reset(); + const gl::Program *program = state.getProgram(); + + translatedAttribs->clear(); + + for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) + { + // Skip attrib locations the program doesn't use. + if (!program->isAttribLocationActive(attribIndex)) + continue; + + const auto &attrib = vertexAttributes[attribIndex]; + + // Resize automatically puts in empty attribs + translatedAttribs->resize(attribIndex + 1); + + TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; + auto currentValueData = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); + + // Record the attribute now + translated->active = true; + translated->attribute = &attrib; + translated->currentValueType = currentValueData.Type; + translated->divisor = attrib.divisor; + + switch (ClassifyAttributeStorage(attrib)) + { + case VertexStorageType::STATIC: + { + // Store static attribute. + ANGLE_TRY(StoreStaticAttrib(translated, count, instances)); + break; + } + case VertexStorageType::DYNAMIC: + // Dynamic attributes must be handled together. + mDynamicAttribsMaskCache.set(attribIndex); + break; + case VertexStorageType::DIRECT: + // Update translated data for direct attributes. + StoreDirectAttrib(translated); + break; + case VertexStorageType::CURRENT_VALUE: + { + ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex)); + break; + } + default: + UNREACHABLE(); + break; + } + } + + if (mDynamicAttribsMaskCache.none()) + { + return gl::NoError(); + } + + ANGLE_TRY( + storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances)); + + PromoteDynamicAttribs(*translatedAttribs, mDynamicAttribsMaskCache, count); + + return gl::NoError(); +} + +// static +void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib) +{ + const auto &attrib = *directAttrib->attribute; + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; + + ASSERT(DirectStoragePossible(attrib)); + directAttrib->vertexBuffer.set(nullptr); + directAttrib->storage = bufferD3D; + directAttrib->serial = bufferD3D->getSerial(); + directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib)); + directAttrib->baseOffset = static_cast<unsigned int>(attrib.offset); + + // Instanced vertices do not apply the 'start' offset + directAttrib->usesFirstVertexOffset = (attrib.divisor == 0); +} + +// static +gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated, + GLsizei count, + GLsizei instances) +{ + const gl::VertexAttribute &attrib = *translated->attribute; + + gl::Buffer *buffer = attrib.buffer.get(); + ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib)); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + + // Compute source data pointer + const uint8_t *sourceData = nullptr; + + ANGLE_TRY(bufferD3D->getData(&sourceData)); + sourceData += static_cast<int>(attrib.offset); + + unsigned int streamOffset = 0; + + translated->storage = nullptr; + ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, 1, 0), + translated->stride); + + auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib); + ASSERT(staticBuffer); + + if (staticBuffer->empty()) + { + // Convert the entire buffer + int totalCount = ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize())); + int startIndex = static_cast<int>(attrib.offset) / + static_cast<int>(ComputeVertexAttributeStride(attrib)); + + ANGLE_TRY( + staticBuffer->storeStaticAttribute(attrib, -startIndex, totalCount, 0, sourceData)); + } + + unsigned int firstElementOffset = + (static_cast<unsigned int>(attrib.offset) / + static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) * + translated->stride; + + VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer(); + + CheckedNumeric<unsigned int> checkedOffset(streamOffset); + checkedOffset += firstElementOffset; + + if (!checkedOffset.IsValid()) + { + return gl::Error(GL_INVALID_OPERATION, + "Integer overflow in VertexDataManager::StoreStaticAttrib"); + } + + translated->vertexBuffer.set(vertexBuffer); + translated->serial = vertexBuffer->getSerial(); + translated->baseOffset = streamOffset + firstElementOffset; + + // Instanced vertices do not apply the 'start' offset + translated->usesFirstVertexOffset = (attrib.divisor == 0); + + return gl::NoError(); +} + +gl::Error VertexDataManager::storeDynamicAttribs( + std::vector<TranslatedAttribute> *translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLint start, + GLsizei count, + GLsizei instances) +{ + // Instantiating this class will ensure the streaming buffer is never left mapped. + class StreamingBufferUnmapper final : NonCopyable + { + public: + StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer) + : mStreamingBuffer(streamingBuffer) + { + ASSERT(mStreamingBuffer); + } + ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); } + + private: + StreamingVertexBufferInterface *mStreamingBuffer; + }; + + // Will trigger unmapping on return. + StreamingBufferUnmapper localUnmapper(mStreamingBuffer); + + // Reserve the required space for the dynamic buffers. + for (auto attribIndex : IterateBitSet(dynamicAttribsMask)) + { + const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; + ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances)); + } + + // Store dynamic attributes + for (auto attribIndex : IterateBitSet(dynamicAttribsMask)) + { + auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; + ANGLE_TRY(storeDynamicAttrib(dynamicAttrib, start, count, instances)); + } + + return gl::NoError(); +} + +void VertexDataManager::PromoteDynamicAttribs( + const std::vector<TranslatedAttribute> &translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLsizei count) +{ + for (auto attribIndex : IterateBitSet(dynamicAttribsMask)) + { + const auto &dynamicAttrib = translatedAttribs[attribIndex]; + gl::Buffer *buffer = dynamicAttrib.attribute->buffer.get(); + if (buffer) + { + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute); + bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); + } + } +} + +gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, + GLsizei count, + GLsizei instances) const +{ + const gl::VertexAttribute &attrib = *translatedAttrib.attribute; + ASSERT(!DirectStoragePossible(attrib)); + + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; + ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib) == nullptr); + + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); + ASSERT(!bufferD3D || + ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize())) >= + static_cast<int>(totalCount)); + + return mStreamingBuffer->reserveVertexSpace(attrib, static_cast<GLsizei>(totalCount), + instances); +} + +gl::Error VertexDataManager::storeDynamicAttrib(TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances) +{ + const gl::VertexAttribute &attrib = *translated->attribute; + + gl::Buffer *buffer = attrib.buffer.get(); + ASSERT(buffer || attrib.pointer); + ASSERT(attrib.enabled); + + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; + + // Instanced vertices do not apply the 'start' offset + GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start); + + // Compute source data pointer + const uint8_t *sourceData = nullptr; + + if (buffer) + { + ANGLE_TRY(storage->getData(&sourceData)); + sourceData += static_cast<int>(attrib.offset); + } + else + { + sourceData = static_cast<const uint8_t*>(attrib.pointer); + } + + unsigned int streamOffset = 0; + + translated->storage = nullptr; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, 1, 0), translated->stride); + + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); + + ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute( + attrib, translated->currentValueType, firstVertexIndex, static_cast<GLsizei>(totalCount), + instances, &streamOffset, sourceData)); + + VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer(); + + translated->vertexBuffer.set(vertexBuffer); + translated->serial = vertexBuffer->getSerial(); + translated->baseOffset = streamOffset; + translated->usesFirstVertexOffset = false; + + return gl::NoError(); +} + +gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + size_t attribIndex) +{ + CurrentValueState *cachedState = &mCurrentValueCache[attribIndex]; + auto *&buffer = cachedState->buffer; + + if (!buffer) + { + buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); + } + + if (cachedState->data != currentValue) + { + const gl::VertexAttribute &attrib = *translated->attribute; + + ANGLE_TRY(buffer->reserveVertexSpace(attrib, 1, 0)); + + const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); + unsigned int streamOffset; + ANGLE_TRY(buffer->storeDynamicAttribute(attrib, currentValue.Type, 0, 1, 0, &streamOffset, + sourceData)); + + buffer->getVertexBuffer()->hintUnmapResource(); + + cachedState->data = currentValue; + cachedState->offset = streamOffset; + } + + translated->vertexBuffer.set(buffer->getVertexBuffer()); + + translated->storage = nullptr; + translated->serial = buffer->getSerial(); + translated->divisor = 0; + translated->stride = 0; + translated->baseOffset = static_cast<unsigned int>(cachedState->offset); + translated->usesFirstVertexOffset = false; + + return gl::NoError(); +} + +// VertexBufferBinding implementation +VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr) +{ +} + +VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other) + : mBoundVertexBuffer(other.mBoundVertexBuffer) +{ + if (mBoundVertexBuffer) + { + mBoundVertexBuffer->addRef(); + } +} + +VertexBufferBinding::~VertexBufferBinding() +{ + if (mBoundVertexBuffer) + { + mBoundVertexBuffer->release(); + } +} + +VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other) +{ + mBoundVertexBuffer = other.mBoundVertexBuffer; + if (mBoundVertexBuffer) + { + mBoundVertexBuffer->addRef(); + } + return *this; +} + +void VertexBufferBinding::set(VertexBuffer *vertexBuffer) +{ + if (mBoundVertexBuffer == vertexBuffer) + return; + + if (mBoundVertexBuffer) + { + mBoundVertexBuffer->release(); + } + if (vertexBuffer) + { + vertexBuffer->addRef(); + } + + mBoundVertexBuffer = vertexBuffer; +} + +VertexBuffer *VertexBufferBinding::get() const +{ + return mBoundVertexBuffer; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h new file mode 100755 index 000000000..da46c7a87 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -0,0 +1,143 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/VertexAttribute.h" + +namespace gl +{ +class State; +struct VertexAttribute; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class BufferD3D; +class BufferFactoryD3D; +class StreamingVertexBufferInterface; +class VertexBuffer; + +class VertexBufferBinding final +{ + public: + VertexBufferBinding(); + VertexBufferBinding(const VertexBufferBinding &other); + ~VertexBufferBinding(); + + void set(VertexBuffer *vertexBuffer); + VertexBuffer *get() const; + VertexBufferBinding &operator=(const VertexBufferBinding &other); + + private: + VertexBuffer *mBoundVertexBuffer; +}; + +struct TranslatedAttribute +{ + TranslatedAttribute(); + + // Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex. + // Can throw an error on integer overflow. + gl::ErrorOrResult<unsigned int> computeOffset(GLint startVertex) const; + + bool active; + + const gl::VertexAttribute *attribute; + GLenum currentValueType; + unsigned int baseOffset; + bool usesFirstVertexOffset; + unsigned int stride; // 0 means not to advance the read pointer at all + + VertexBufferBinding vertexBuffer; + BufferD3D *storage; + unsigned int serial; + unsigned int divisor; +}; + +enum class VertexStorageType +{ + UNKNOWN, + STATIC, // Translate the vertex data once and re-use it. + DYNAMIC, // Translate the data every frame into a ring buffer. + DIRECT, // Bind a D3D buffer directly without any translation. + CURRENT_VALUE, // Use a single value for the attribute. +}; + +// Given a vertex attribute, return the type of storage it will use. +VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib); + +class VertexDataManager : angle::NonCopyable +{ + public: + VertexDataManager(BufferFactoryD3D *factory); + virtual ~VertexDataManager(); + + gl::Error prepareVertexData(const gl::State &state, + GLint start, + GLsizei count, + std::vector<TranslatedAttribute> *translatedAttribs, + GLsizei instances); + + static void StoreDirectAttrib(TranslatedAttribute *directAttrib); + + static gl::Error StoreStaticAttrib(TranslatedAttribute *translated, + GLsizei count, + GLsizei instances); + + gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLint start, + GLsizei count, + GLsizei instances); + + // Promote static usage of dynamic buffers. + static void PromoteDynamicAttribs(const std::vector<TranslatedAttribute> &translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLsizei count); + + gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + size_t attribIndex); + + private: + struct CurrentValueState + { + CurrentValueState(); + ~CurrentValueState(); + + StreamingVertexBufferInterface *buffer; + gl::VertexAttribCurrentValueData data; + size_t offset; + }; + + gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, + GLsizei count, + GLsizei instances) const; + + gl::Error storeDynamicAttrib(TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances); + + BufferFactoryD3D *const mFactory; + + StreamingVertexBufferInterface *mStreamingBuffer; + std::vector<CurrentValueState> mCurrentValueCache; + gl::AttributesMask mDynamicAttribsMaskCache; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h new file mode 100755 index 000000000..ede929ce8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h @@ -0,0 +1,111 @@ +// +// 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. +// + +// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues. + +#ifndef LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ +#define LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ + +// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate +// independent of ANGLE's renderer. Workarounds should also be accessible +// outside of the Renderer. + +namespace rx +{ +struct D3DCompilerWorkarounds +{ + bool skipOptimization = false; + bool useMaxOptimization = false; + + // IEEE strictness needs to be enabled for NANs to work. + bool enableIEEEStrictness = false; +}; + +struct WorkaroundsD3D +{ + // On some systems, having extra rendertargets than necessary slows down the shader. + // We can fix this by optimizing those out of the shader. At the same time, we can + // work around a bug on some nVidia drivers that they ignore "null" render targets + // in D3D11, by compacting the active color attachments list to omit null entries. + bool mrtPerfWorkaround = false; + + bool setDataFasterThanImageUpload = false; + + // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level + // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to + // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no + // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an + // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST + // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the + // texture. The textures' level zeros are identical, but only one texture has mips. + bool zeroMaxLodWorkaround = false; + + // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite + // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite + // emulation that is implemented using instanced quads. + bool useInstancedPointSpriteEmulation = false; + + // A bug fixed in NVIDIA driver version 347.88 < x <= 368.81 triggers a TDR when using + // CopySubresourceRegion from a staging texture to a depth/stencil in D3D11. The workaround + // is to use UpdateSubresource to trigger an extra copy. We disable this workaround on newer + // NVIDIA driver versions because of a second driver bug present with the workaround enabled. + // (See: http://anglebug.com/1452) + bool depthStencilBlitExtraCopy = false; + + // The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions. + // We can work around this by expanding the pow into a series of multiplies if we're running + // under the affected compiler. + bool expandIntegerPowExpressions = false; + + // NVIDIA drivers sometimes write out-of-order results to StreamOut buffers when transform + // feedback is used to repeatedly write to the same buffer positions. + bool flushAfterEndingTransformFeedback = false; + + // Some drivers (NVIDIA) do not take into account the base level of the texture in the results + // of the HLSL GetDimensions builtin. + bool getDimensionsIgnoresBaseLevel = false; + + // On some Intel drivers, HLSL's function texture.Load returns 0 when the parameter Location + // is negative, even if the sum of Offset and Location is in range. This may cause errors when + // translating GLSL's function texelFetchOffset into texture.Load, as it is valid for + // texelFetchOffset to use negative texture coordinates as its parameter P when the sum of P + // and Offset is in range. To work around this, we translate texelFetchOffset into texelFetch + // by adding Offset directly to Location before reading the texture. + bool preAddTexelFetchOffsets = false; + + // On some AMD drivers, 1x1 and 2x2 mips of depth/stencil textures aren't sampled correctly. + // We can work around this bug by doing an internal blit to a temporary single-channel texture + // before we sample. + bool emulateTinyStencilTextures = false; + + // In Intel driver, the data with format DXGI_FORMAT_B5G6R5_UNORM will be parsed incorrectly. + // This workaroud will disable B5G6R5 support when it's Intel driver. By default, it will use + // R8G8B8A8 format. + bool disableB5G6R5Support = false; + + // On some Intel drivers, evaluating unary minus operator on integer may get wrong answer in + // vertex shaders. To work around this bug, we translate -(int) into ~(int)+1. + bool rewriteUnaryMinusOperator = false; + + // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around + // this bug, we use an expression to emulate function isnan(). Tracking bug: + // https://crbug.com/650547 + bool emulateIsnanFloat = false; + + // On some Intel drivers, using clear() may not take effect. To work around this bug, we call + // clear() twice on these platforms. Tracking bug: https://crbug.com/655534 + bool callClearTwice = false; + + // On some Intel drivers, copying from staging storage to constant buffer storage does not + // seem to work. Work around this by keeping system memory storage as a canonical reference + // for buffer data. + // D3D11-only workaround. See http://crbug.com/593024. + bool useSystemMemoryForConstantBuffers = false; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp new file mode 100755 index 000000000..f8a0ac597 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -0,0 +1,2250 @@ +// +// Copyright (c) 2013 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. +// + +// Blit11.cpp: Texture copy utility class. + +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" + +#include <float.h> + +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "third_party/trace_event/trace_event.h" + +namespace rx +{ + +namespace +{ + +// Include inline shaders in the anonymous namespace to make sure no symbols are exported +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" + +void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + size_t pixelSize, + const uint8_t *sourceData, + uint8_t *destData) +{ + int srcHeightSubOne = (sourceArea.height - 1); + size_t copySize = pixelSize * destArea.width; + size_t srcOffset = sourceArea.x * pixelSize; + size_t destOffset = destArea.x * pixelSize; + + for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) + { + float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1); + + // Interpolate using the original source rectangle to determine which row to sample from + // while clamping to the edges + unsigned int readRow = static_cast<unsigned int>( + gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne)); + unsigned int writeRow = y; + + const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset; + uint8_t *destRow = destData + writeRow * destRowPitch + destOffset; + memcpy(destRow, sourceRow, copySize); + } +} + +void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + auto xMax = clippedDestArea.x + clippedDestArea.width; + auto yMax = clippedDestArea.y + clippedDestArea.height; + + for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++) + { + // Interpolate using the original source rectangle to determine which row to sample from + // while clamping to the edges + float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1); + float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f); + unsigned int readRow = + static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1)); + + for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++) + { + // Interpolate the original source rectangle to determine which column to sample + // from while clamping to the edges + float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1); + float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f); + unsigned int readColumn = static_cast<unsigned int>( + gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1)); + + const uint8_t *sourcePixel = + sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset; + + uint8_t *destPixel = + destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset; + + memcpy(destPixel, sourcePixel, copySize); + } + } +} + +void StretchedBlitNearest(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clipRect, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); + gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea); + + // Determine if entire rows can be copied at once instead of each individual pixel. There + // must be no out of bounds lookups, whole rows copies, and no scale. + if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 && + sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride && + copySize == destPixelStride) + { + StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize, + sourceRowPitch, destRowPitch, srcPixelStride, sourceData, + destData); + } + else + { + StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize, + sourceRowPitch, destRowPitch, readOffset, writeOffset, + copySize, srcPixelStride, destPixelStride, sourceData, + destData); + } +} + +using DepthStencilLoader = void(const float *, uint8_t *); + +void LoadDepth16(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 2u); +} + +void LoadDepth24(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 3u); +} + +void LoadStencilHelper(const float *source, uint8_t *dest) +{ + uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1])); + memcpy(dest, &convertedStencil, 1u); +} + +void LoadStencil8(const float *source, uint8_t *dest) +{ + // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety. + float zero = 0.0f; + LoadDepth24(&zero, &dest[0]); + LoadStencilHelper(source, &dest[3]); +} + +void LoadDepth24Stencil8(const float *source, uint8_t *dest) +{ + LoadDepth24(source, &dest[0]); + LoadStencilHelper(source, &dest[3]); +} + +void LoadDepth32F(const float *source, uint8_t *dest) +{ + memcpy(dest, source, sizeof(float)); +} + +void LoadDepth32FStencil8(const float *source, uint8_t *dest) +{ + LoadDepth32F(source, &dest[0]); + LoadStencilHelper(source, &dest[4]); +} + +template <DepthStencilLoader loader> +void CopyDepthStencil(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) + { + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset); + + uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride; + + loader(sourcePixel, destPixel); + } + } +} + +void Depth32FStencil8ToDepth32F(const float *source, float *dest) +{ + *dest = *source; +} + +void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest) +{ + uint32_t normDepth = source[0] & 0x00FFFFFF; + float floatDepth = gl::normalizedToFloat<24>(normDepth); + *dest = floatDepth; +} + +void BlitD24S8ToD32F(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) + { + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset); + + float *destPixel = + reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride); + + Depth24Stencil8ToDepth32F(sourcePixel, destPixel); + } + } +} + +void BlitD32FS8ToD32F(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) + { + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset); + float *destPixel = + reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride); + + Depth32FStencil8ToDepth32F(sourcePixel, destPixel); + } + } +} + +Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat) +{ + switch (internalFormat) + { + case GL_DEPTH_COMPONENT16: + return &CopyDepthStencil<LoadDepth16>; + case GL_DEPTH_COMPONENT24: + return &CopyDepthStencil<LoadDepth24>; + case GL_DEPTH_COMPONENT32F: + return &CopyDepthStencil<LoadDepth32F>; + case GL_STENCIL_INDEX8: + return &CopyDepthStencil<LoadStencil8>; + case GL_DEPTH24_STENCIL8: + return &CopyDepthStencil<LoadDepth24Stencil8>; + case GL_DEPTH32F_STENCIL8: + return &CopyDepthStencil<LoadDepth32FStencil8>; + default: + UNREACHABLE(); + return nullptr; + } +} + +inline void GenerateVertexCoords(const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const gl::Box &destArea, + const gl::Extents &destSize, + float *x1, + float *y1, + float *x2, + float *y2, + float *u1, + float *v1, + float *u2, + float *v2) +{ + *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; + *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f; + *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f; + + *u1 = sourceArea.x / float(sourceSize.width); + *v1 = sourceArea.y / float(sourceSize.height); + *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width); + *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); +} + +void Write2DVertices(const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const gl::Box &destArea, + const gl::Extents &destSize, + void *outVertices, + unsigned int *outStride, + unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); + + d3d11::PositionTexCoordVertex *vertices = + static_cast<d3d11::PositionTexCoordVertex *>(outVertices); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + + *outStride = sizeof(d3d11::PositionTexCoordVertex); + *outVertexCount = 4; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; +} + +void Write3DVertices(const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const gl::Box &destArea, + const gl::Extents &destSize, + void *outVertices, + unsigned int *outStride, + unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + ASSERT(sourceSize.depth > 0 && destSize.depth > 0); + + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); + + d3d11::PositionLayerTexCoord3DVertex *vertices = + static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices); + + for (int i = 0; i < destSize.depth; i++) + { + float readDepth = (float)i / std::max(destSize.depth - 1, 1); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); + } + + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outVertexCount = destSize.depth * 6; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; +} + +unsigned int GetSwizzleIndex(GLenum swizzle) +{ + unsigned int colorIndex = 0; + + switch (swizzle) + { + case GL_RED: + colorIndex = 0; + break; + case GL_GREEN: + colorIndex = 1; + break; + case GL_BLUE: + colorIndex = 2; + break; + case GL_ALPHA: + colorIndex = 3; + break; + case GL_ZERO: + colorIndex = 4; + break; + case GL_ONE: + colorIndex = 5; + break; + default: + UNREACHABLE(); + break; + } + + return colorIndex; +} + +D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc() +{ + D3D11_BLEND_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | + D3D11_COLOR_WRITE_ENABLE_GREEN | + D3D11_COLOR_WRITE_ENABLE_BLUE; + return desc; +} + +D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, +}; + +D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, +}; + +DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet) +{ + switch (formatSet.texFormat) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + case DXGI_FORMAT_R24G8_TYPELESS: + return DXGI_FORMAT_X24_TYPELESS_G8_UINT; + default: + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +} // namespace + +Blit11::Blit11(Renderer11 *renderer) + : mRenderer(renderer), + mResourcesInitialized(false), + mVertexBuffer(nullptr), + mPointSampler(nullptr), + mLinearSampler(nullptr), + mScissorEnabledRasterizerState(nullptr), + mScissorDisabledRasterizerState(nullptr), + mDepthStencilState(nullptr), + mQuad2DIL(quad2DLayout, + ArraySize(quad2DLayout), + g_VS_Passthrough2D, + ArraySize(g_VS_Passthrough2D), + "Blit11 2D input layout"), + mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"), + mDepthPS(g_PS_PassthroughDepth2D, + ArraySize(g_PS_PassthroughDepth2D), + "Blit11 2D depth pixel shader"), + mQuad3DIL(quad3DLayout, + ArraySize(quad3DLayout), + g_VS_Passthrough3D, + ArraySize(g_VS_Passthrough3D), + "Blit11 3D input layout"), + mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"), + mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"), + mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"), + mSwizzleCB(nullptr), + mResolveDepthStencilVS(g_VS_ResolveDepthStencil, + ArraySize(g_VS_ResolveDepthStencil), + "Blit11::mResolveDepthStencilVS"), + mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"), + mResolveDepthStencilPS(g_PS_ResolveDepthStencil, + ArraySize(g_PS_ResolveDepthStencil), + "Blit11::mResolveDepthStencilPS"), + mResolveStencilPS(g_PS_ResolveStencil, + ArraySize(g_PS_ResolveStencil), + "Blit11::mResolveStencilPS"), + mStencilSRV(nullptr), + mResolvedDepthStencilRTView(nullptr) +{ +} + +Blit11::~Blit11() +{ + freeResources(); + + mQuad2DIL.release(); + mQuad2DVS.release(); + mDepthPS.release(); + + mQuad3DIL.release(); + mQuad3DVS.release(); + mQuad3DGS.release(); + + clearShaderMap(); + releaseResolveDepthStencilResources(); +} + +gl::Error Blit11::initResources() +{ + if (mResourcesInitialized) + { + return gl::Error(GL_NO_ERROR); + } + + TRACE_EVENT0("gpu.angle", "Blit11::initResources"); + + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = + static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), + sizeof(d3d11::PositionTexCoordVertex)) * + 6 * mRenderer->getNativeCaps().max3DTextureSize); + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X", + result); + } + d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); + + D3D11_SAMPLER_DESC pointSamplerDesc; + pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.MipLODBias = 0.0f; + pointSamplerDesc.MaxAnisotropy = 0; + pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + pointSamplerDesc.BorderColor[0] = 0.0f; + pointSamplerDesc.BorderColor[1] = 0.0f; + pointSamplerDesc.BorderColor[2] = 0.0f; + pointSamplerDesc.BorderColor[3] = 0.0f; + pointSamplerDesc.MinLOD = 0.0f; + pointSamplerDesc.MaxLOD = FLT_MAX; + + result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit point sampler state, HRESULT: 0x%X", result); + } + d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); + + D3D11_SAMPLER_DESC linearSamplerDesc; + linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.MipLODBias = 0.0f; + linearSamplerDesc.MaxAnisotropy = 0; + linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + linearSamplerDesc.BorderColor[0] = 0.0f; + linearSamplerDesc.BorderColor[1] = 0.0f; + linearSamplerDesc.BorderColor[2] = 0.0f; + linearSamplerDesc.BorderColor[3] = 0.0f; + linearSamplerDesc.MinLOD = 0.0f; + linearSamplerDesc.MaxLOD = FLT_MAX; + + result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit linear sampler state, HRESULT: 0x%X", result); + } + d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); + + // Use a rasterizer state that will not cull so that inverted quads will not be culled + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + rasterDesc.ScissorEnable = TRUE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X", + result); + } + d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); + + rasterDesc.ScissorEnable = FALSE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X", + result); + } + d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit depth stencil state, HRESULT: 0x%X", result); + } + d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); + + D3D11_BUFFER_DESC swizzleBufferDesc; + swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; + swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + swizzleBufferDesc.MiscFlags = 0; + swizzleBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X", + result); + } + d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); + + mResourcesInitialized = true; + + return gl::Error(GL_NO_ERROR); +} + +void Blit11::freeResources() +{ + SafeRelease(mVertexBuffer); + SafeRelease(mPointSampler); + SafeRelease(mLinearSampler); + SafeRelease(mScissorEnabledRasterizerState); + SafeRelease(mScissorDisabledRasterizerState); + SafeRelease(mDepthStencilState); + SafeRelease(mSwizzleCB); + + mResourcesInitialized = false; +} + +// static +Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension) +{ + if (dimension == SHADER_3D) + { + ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha); + + if (isSigned) + { + switch (destinationFormat) + { + case GL_RGBA_INTEGER: + return BLITSHADER_3D_RGBAI; + case GL_RGB_INTEGER: + return BLITSHADER_3D_RGBI; + case GL_RG_INTEGER: + return BLITSHADER_3D_RGI; + case GL_RED_INTEGER: + return BLITSHADER_3D_RI; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + else + { + switch (destinationFormat) + { + case GL_RGBA: + return BLITSHADER_3D_RGBAF; + case GL_RGBA_INTEGER: + return BLITSHADER_3D_RGBAUI; + case GL_BGRA_EXT: + return BLITSHADER_3D_BGRAF; + case GL_RGB: + return BLITSHADER_3D_RGBF; + case GL_RGB_INTEGER: + return BLITSHADER_3D_RGBUI; + case GL_RG: + return BLITSHADER_3D_RGF; + case GL_RG_INTEGER: + return BLITSHADER_3D_RGUI; + case GL_RED: + return BLITSHADER_3D_RF; + case GL_RED_INTEGER: + return BLITSHADER_3D_RUI; + case GL_ALPHA: + return BLITSHADER_3D_ALPHA; + case GL_LUMINANCE: + return BLITSHADER_3D_LUMA; + case GL_LUMINANCE_ALPHA: + return BLITSHADER_3D_LUMAALPHA; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + } + else if (isSigned) + { + ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha); + + switch (destinationFormat) + { + case GL_RGBA_INTEGER: + return BLITSHADER_2D_RGBAI; + case GL_RGB_INTEGER: + return BLITSHADER_2D_RGBI; + case GL_RG_INTEGER: + return BLITSHADER_2D_RGI; + case GL_RED_INTEGER: + return BLITSHADER_2D_RI; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + else + { + if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha) + { + switch (destinationFormat) + { + case GL_RGBA: + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY + : BLITSHADER_2D_RGBAF_UNMULTIPLY; + case GL_BGRA_EXT: + return unpackPremultiplyAlpha ? BLITSHADER_2D_BGRAF_PREMULTIPLY + : BLITSHADER_2D_BGRAF_UNMULTIPLY; + case GL_RGB: + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY + : BLITSHADER_2D_RGBF_UNMULTIPLY; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + else + { + switch (destinationFormat) + { + case GL_RGBA: + return BLITSHADER_2D_RGBAF; + case GL_RGBA_INTEGER: + return BLITSHADER_2D_RGBAUI; + case GL_BGRA_EXT: + return BLITSHADER_2D_BGRAF; + case GL_RGB: + return BLITSHADER_2D_RGBF; + case GL_RGB_INTEGER: + return BLITSHADER_2D_RGBUI; + case GL_RG: + return BLITSHADER_2D_RGF; + case GL_RG_INTEGER: + return BLITSHADER_2D_RGUI; + case GL_RED: + return BLITSHADER_2D_RF; + case GL_RED_INTEGER: + return BLITSHADER_2D_RUI; + case GL_ALPHA: + return BLITSHADER_2D_ALPHA; + case GL_LUMINANCE: + return BLITSHADER_2D_LUMA; + case GL_LUMINANCE_ALPHA: + return BLITSHADER_2D_LUMAALPHA; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + } +} + +// static +Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type, + D3D11_SRV_DIMENSION dimensionality) +{ + switch (dimensionality) + { + case D3D11_SRV_DIMENSION_TEXTURE2D: + switch (type) + { + case GL_FLOAT: + return SWIZZLESHADER_2D_FLOAT; + case GL_UNSIGNED_INT: + return SWIZZLESHADER_2D_UINT; + case GL_INT: + return SWIZZLESHADER_2D_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURECUBE: + switch (type) + { + case GL_FLOAT: + return SWIZZLESHADER_CUBE_FLOAT; + case GL_UNSIGNED_INT: + return SWIZZLESHADER_CUBE_UINT; + case GL_INT: + return SWIZZLESHADER_CUBE_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURE3D: + switch (type) + { + case GL_FLOAT: + return SWIZZLESHADER_3D_FLOAT; + case GL_UNSIGNED_INT: + return SWIZZLESHADER_3D_UINT; + case GL_INT: + return SWIZZLESHADER_3D_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + switch (type) + { + case GL_FLOAT: + return SWIZZLESHADER_ARRAY_FLOAT; + case GL_UNSIGNED_INT: + return SWIZZLESHADER_ARRAY_UINT; + case GL_INT: + return SWIZZLESHADER_ARRAY_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } +} + +Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader) +{ + ID3D11Device *device = mRenderer->getDevice(); + ShaderSupport support; + + if (shader.dimension == SHADER_2D) + { + support.inputLayout = mQuad2DIL.resolve(device); + support.vertexShader = mQuad2DVS.resolve(device); + support.geometryShader = nullptr; + support.vertexWriteFunction = Write2DVertices; + } + else + { + ASSERT(shader.dimension == SHADER_3D); + support.inputLayout = mQuad3DIL.resolve(device); + support.vertexShader = mQuad3DVS.resolve(device); + support.geometryShader = mQuad3DGS.resolve(device); + support.vertexWriteFunction = Write3DVertices; + } + + return support; +} + +gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, + ID3D11RenderTargetView *dest, + const gl::Extents &size, + const gl::SwizzleState &swizzleTarget) +{ + ANGLE_TRY(initResources()); + + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + + GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format); + if (componentType == GL_NONE) + { + // We're swizzling the depth component of a depth-stencil texture. + switch (sourceSRVDesc.Format) + { + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + componentType = GL_UNSIGNED_NORMALIZED; + break; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + componentType = GL_FLOAT; + break; + default: + UNREACHABLE(); + break; + } + } + + GLenum shaderType = GL_NONE; + switch (componentType) + { + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + shaderType = GL_FLOAT; + break; + case GL_INT: + shaderType = GL_INT; + break; + case GL_UNSIGNED_INT: + shaderType = GL_UNSIGNED_INT; + break; + default: + UNREACHABLE(); + break; + } + + const Shader *shader = nullptr; + ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader)); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", + result); + } + + const ShaderSupport &support = getShaderSupport(*shader); + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, + &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set constant buffer + result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.", + result); + } + + unsigned int *swizzleIndices = reinterpret_cast<unsigned int *>(mappedResource.pData); + swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed); + swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen); + swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue); + swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha); + + deviceContext->Unmap(mSwizzleCB, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply constant buffer + deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + + // Apply state + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + deviceContext->RSSetState(mScissorDisabledRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(support.inputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(support.vertexShader, nullptr, 0); + + deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); + deviceContext->GSSetShader(support.geometryShader, nullptr, 0); + + // Unset the currently bound shader resource to avoid conflicts + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + // Apply render target + stateManager->setOneTimeRenderTarget(dest, nullptr); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(size.width); + viewport.Height = static_cast<FLOAT>(size.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = nullptr; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + ANGLE_TRY(initResources()); + + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Determine if the source format is a signed integer format, the destFormat will already + // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + + GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format); + + ASSERT(componentType != GL_NONE); + ASSERT(componentType != GL_SIGNED_NORMALIZED); + bool isSigned = (componentType == GL_INT); + + ShaderDimension dimension = + (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; + + const Shader *shader = nullptr; + ANGLE_TRY(getBlitShader(destFormat, isSigned, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, + dimension, &shader)); + + const ShaderSupport &support = getShaderSupport(*shader); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", + result); + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + if (maskOffAlpha) + { + ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice()); + ASSERT(blendState); + deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF); + } + else + { + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + } + deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(support.inputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(support.vertexShader, nullptr, 0); + + deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); + deviceContext->GSSetShader(support.geometryShader, nullptr, 0); + + // Unset the currently bound shader resource to avoid conflicts + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + // Apply render target + stateManager->setOneTimeRenderTarget(dest, nullptr); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(destSize.width); + viewport.Height = static_cast<FLOAT>(destSize.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + ID3D11SamplerState *sampler = nullptr; + switch (filter) + { + case GL_NEAREST: + sampler = mPointSampler; + break; + case GL_LINEAR: + sampler = mLinearSampler; + break; + + default: + UNREACHABLE(); + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode."); + } + deviceContext->PSSetSamplers(0, 1, &sampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = nullptr; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::NoError(); +} + +gl::Error Blit11::copyStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, true); +} + +gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + ANGLE_TRY(initResources()); + + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", + result); + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, + &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device); + if (quad2DVS == nullptr) + { + return gl::Error(GL_INVALID_OPERATION, "Error compiling internal 2D blit vertex shader"); + } + + // Apply shaders + deviceContext->IASetInputLayout(mQuad2DIL.resolve(device)); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(quad2DVS, nullptr, 0); + + deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0); + deviceContext->GSSetShader(nullptr, nullptr, 0); + + // Unset the currently bound shader resource to avoid conflicts + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + // Apply render target + stateManager->setOneTimeRenderTarget(nullptr, dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(destSize.width); + viewport.Height = static_cast<FLOAT>(destSize.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = nullptr; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::copyDepthStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, false); +} + +gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + bool stencilOnly) +{ + auto srcDXGIFormat = source.getFormat(); + const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat); + unsigned int srcPixelSize = srcSizeInfo.pixelBytes; + unsigned int copyOffset = 0; + unsigned int copySize = srcPixelSize; + auto destDXGIFormat = dest.getFormat(); + const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat); + unsigned int destPixelSize = destSizeInfo.pixelBytes; + + ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS); + + if (stencilOnly) + { + const auto &srcFormat = source.getFormatSet().format(); + + // Stencil channel should be right after the depth channel. Some views to depth/stencil + // resources have red channel for depth, in which case the depth channel bit width is in + // redBits. + ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0)); + GLuint depthBits = srcFormat.redBits + srcFormat.depthBits; + // Known formats have either 24 or 32 bits of depth. + ASSERT(depthBits == 24 || depthBits == 32); + copyOffset = depthBits / 8; + + // Stencil is assumed to be 8-bit - currently this is true for all possible formats. + copySize = 1; + } + + if (srcDXGIFormat != destDXGIFormat) + { + if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS) + { + ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, copyOffset, + copyOffset, copySize, srcPixelSize, destPixelSize, + BlitD24S8ToD32F); + } + ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, copyOffset, copyOffset, + copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F); + } + + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource, + destArea, destSize, scissor, copyOffset, copyOffset, copySize, + srcPixelSize, destPixelSize, StretchedBlitNearest); +} + +gl::Error Blit11::copyAndConvertImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &destStaging, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction) +{ + ANGLE_TRY(initResources()); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + TextureHelper11 sourceStaging; + ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, source.getFormatSet(), sourceSize, + StagingAccess::READ, device), + sourceStaging); + + deviceContext->CopySubresourceRegion(sourceStaging.getResource(), 0, 0, 0, 0, + source.getResource(), sourceSubresource, nullptr); + + D3D11_MAPPED_SUBRESOURCE sourceMapping; + HRESULT result = + deviceContext->Map(sourceStaging.getResource(), 0, D3D11_MAP_READ, 0, &sourceMapping); + if (FAILED(result)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", + result); + } + + D3D11_MAPPED_SUBRESOURCE destMapping; + result = deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_WRITE, 0, &destMapping); + if (FAILED(result)) + { + deviceContext->Unmap(sourceStaging.getResource(), 0); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal destination staging texture for depth stencil " + "blit, HRESULT: 0x%X.", + result); + } + + // Clip dest area to the destination size + gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height); + + // Clip dest area to the scissor + if (scissor) + { + gl::ClipRectangle(clipRect, *scissor, &clipRect); + } + + convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch, + destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride, + destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData), + static_cast<uint8_t *>(destMapping.pData)); + + deviceContext->Unmap(sourceStaging.getResource(), 0); + deviceContext->Unmap(destStaging.getResource(), 0); + + return gl::NoError(); +} + +gl::Error Blit11::copyAndConvert(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction) +{ + ANGLE_TRY(initResources()); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // HACK: Create the destination staging buffer as a read/write texture so + // ID3D11DevicContext::UpdateSubresource can be called + // using it's mapped data as a source + TextureHelper11 destStaging; + ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, dest.getFormatSet(), destSize, + StagingAccess::READ_WRITE, device), + destStaging); + + deviceContext->CopySubresourceRegion(destStaging.getResource(), 0, 0, 0, 0, dest.getResource(), + destSubresource, nullptr); + + copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, destArea, + destSize, scissor, readOffset, writeOffset, copySize, srcPixelStride, + destPixelStride, convertFunction); + + // Work around timeouts/TDRs in older NVIDIA drivers. + if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy) + { + D3D11_MAPPED_SUBRESOURCE mapped; + deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_READ, 0, &mapped); + deviceContext->UpdateSubresource(dest.getResource(), destSubresource, nullptr, mapped.pData, + mapped.RowPitch, mapped.DepthPitch); + deviceContext->Unmap(destStaging.getResource(), 0); + } + else + { + deviceContext->CopySubresourceRegion(dest.getResource(), destSubresource, 0, 0, 0, + destStaging.getResource(), 0, nullptr); + } + + return gl::NoError(); +} + +void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + ID3D11PixelShader *ps) +{ + ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.dimension = dimension; + shader.pixelShader = ps; + + mBlitShaderMap[blitShaderType] = shader; +} + +void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + ID3D11PixelShader *ps) +{ + ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.dimension = dimension; + shader.pixelShader = ps; + + mSwizzleShaderMap[swizzleShaderType] = shader; +} + +void Blit11::clearShaderMap() +{ + for (auto &blitShader : mBlitShaderMap) + { + SafeRelease(blitShader.second.pixelShader); + } + mBlitShaderMap.clear(); + + for (auto &swizzleShader : mSwizzleShaderMap) + { + SafeRelease(swizzleShader.second.pixelShader); + } + mSwizzleShaderMap.clear(); +} + +gl::Error Blit11::getBlitShader(GLenum destFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shader) +{ + BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha, dimension); + + if (blitShaderType == BLITSHADER_INVALID) + { + return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch"); + } + + auto blitShaderIt = mBlitShaderMap.find(blitShaderType); + if (blitShaderIt != mBlitShaderMap.end()) + { + *shader = &blitShaderIt->second; + return gl::Error(GL_NO_ERROR); + } + + ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable()); + + ID3D11Device *device = mRenderer->getDevice(); + + switch (blitShaderType) + { + case BLITSHADER_2D_RGBAF: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader")); + break; + case BLITSHADER_2D_RGBAF_PREMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D, + "Blit11 2D RGBA premultiply pixel shader")); + break; + case BLITSHADER_2D_RGBAF_UNMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D, + "Blit11 2D RGBA unmultiply pixel shader")); + break; + case BLITSHADER_2D_BGRAF: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader")); + break; + case BLITSHADER_2D_BGRAF_PREMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D, + "Blit11 2D BGRA premultiply pixel shader")); + break; + case BLITSHADER_2D_BGRAF_UNMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D, + "Blit11 2D BGRA unmultiply pixel shader")); + break; + case BLITSHADER_2D_RGBF: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader")); + break; + case BLITSHADER_2D_RGBF_PREMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBPremultiply2D, + "Blit11 2D RGB premultiply pixel shader")); + break; + case BLITSHADER_2D_RGBF_UNMULTIPLY: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBUnmultiply2D, + "Blit11 2D RGB unmultiply pixel shader")); + break; + case BLITSHADER_2D_RGF: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader")); + break; + case BLITSHADER_2D_RF: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader")); + break; + case BLITSHADER_2D_ALPHA: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader")); + break; + case BLITSHADER_2D_LUMA: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHA: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, + "Blit11 2D luminance alpha pixel shader")); + break; + case BLITSHADER_2D_RGBAUI: + addBlitShaderToMap(blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, + "Blit11 2D RGBA UI pixel shader")); + break; + case BLITSHADER_2D_RGBAI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader")); + break; + case BLITSHADER_2D_RGBUI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader")); + break; + case BLITSHADER_2D_RGBI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader")); + break; + case BLITSHADER_2D_RGUI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader")); + break; + case BLITSHADER_2D_RGI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader")); + break; + case BLITSHADER_2D_RUI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader")); + break; + case BLITSHADER_2D_RI: + addBlitShaderToMap( + blitShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader")); + break; + case BLITSHADER_3D_RGBAF: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAUI: + addBlitShaderToMap(blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, + "Blit11 3D UI RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader")); + break; + case BLITSHADER_3D_BGRAF: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader")); + break; + case BLITSHADER_3D_RGBF: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader")); + break; + case BLITSHADER_3D_RGBUI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader")); + break; + case BLITSHADER_3D_RGBI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader")); + break; + case BLITSHADER_3D_RGF: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader")); + break; + case BLITSHADER_3D_RGUI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader")); + break; + case BLITSHADER_3D_RGI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader")); + break; + case BLITSHADER_3D_RF: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader")); + break; + case BLITSHADER_3D_RUI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader")); + break; + case BLITSHADER_3D_RI: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader")); + break; + case BLITSHADER_3D_ALPHA: + addBlitShaderToMap( + blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader")); + break; + case BLITSHADER_3D_LUMA: + addBlitShaderToMap(blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughLum3D, + "Blit11 3D luminance pixel shader")); + break; + case BLITSHADER_3D_LUMAALPHA: + addBlitShaderToMap(blitShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, + "Blit11 3D luminance alpha pixel shader")); + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error"); + } + + blitShaderIt = mBlitShaderMap.find(blitShaderType); + ASSERT(blitShaderIt != mBlitShaderMap.end()); + *shader = &blitShaderIt->second; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::getSwizzleShader(GLenum type, + D3D11_SRV_DIMENSION viewDimension, + const Shader **shader) +{ + SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension); + + if (swizzleShaderType == SWIZZLESHADER_INVALID) + { + return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found"); + } + + auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); + if (swizzleShaderIt != mSwizzleShaderMap.end()) + { + *shader = &swizzleShaderIt->second; + return gl::Error(GL_NO_ERROR); + } + + // Swizzling shaders (OpenGL ES 3+) + ASSERT(mRenderer->isES3Capable()); + + ID3D11Device *device = mRenderer->getDevice(); + + switch (swizzleShaderType) + { + case SWIZZLESHADER_2D_FLOAT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_UINT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_INT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_2D, + d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleF2DArray, + "Blit11 2D Cube F swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, + "Blit11 2D Cube UI swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleI2DArray, + "Blit11 2D Cube I swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_FLOAT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_UINT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_INT: + addSwizzleShaderToMap( + swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleF2DArray, + "Blit11 2D Array F swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, + "Blit11 2D Array UI swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + d3d11::CompilePS(device, g_PS_SwizzleI2DArray, + "Blit11 2D Array I swizzle pixel shader")); + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error"); + } + + swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); + ASSERT(swizzleShaderIt != mSwizzleShaderMap.end()); + *shader = &swizzleShaderIt->second; + return gl::NoError(); +} + +gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(RenderTarget11 *depth) +{ + // Multisampled depth stencil SRVs are not available in feature level 10.0 + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0) + { + return gl::Error(GL_INVALID_OPERATION, + "Resolving multisampled depth stencil textures is not supported in " + "feature level 10.0."); + } + + const auto &extents = depth->getExtents(); + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + ANGLE_TRY(initResolveDepthStencil(extents)); + + // Notify the Renderer that all state should be invalidated. + mRenderer->markAllStateDirty(); + + // Apply the necessary state changes to the D3D11 immediate device context. + context->IASetInputLayout(nullptr); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0); + context->GSSetShader(nullptr, nullptr, 0); + context->RSSetState(nullptr); + context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr); + context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(extents.width); + viewport.Height = static_cast<FLOAT>(extents.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + context->RSSetViewports(1, &viewport); + + ID3D11ShaderResourceView *pixelViews[] = {depth->getShaderResourceView()}; + + context->PSSetShaderResources(0, 1, pixelViews); + + context->PSSetShader(mResolveDepthPS.resolve(device), nullptr, 0); + + // Trigger the blit on the GPU. + context->Draw(6, 0); + + gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1); + + const auto ©Function = GetCopyDepthStencilFunction(depth->getInternalFormat()); + const auto &dsFormatSet = depth->getFormatSet(); + const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat); + + ID3D11Texture2D *destTex = nullptr; + + D3D11_TEXTURE2D_DESC destDesc; + destDesc.Width = extents.width; + destDesc.Height = extents.height; + destDesc.MipLevels = 1; + destDesc.ArraySize = 1; + destDesc.Format = dsFormatSet.texFormat; + destDesc.SampleDesc.Count = 1; + destDesc.SampleDesc.Quality = 0; + destDesc.Usage = D3D11_USAGE_DEFAULT; + destDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + destDesc.CPUAccessFlags = 0; + destDesc.MiscFlags = 0; + + HRESULT hr = device->CreateTexture2D(&destDesc, nullptr, &destTex); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Error creating depth resolve dest texture."); + } + d3d11::SetDebugName(destTex, "resolveDepthDest"); + + TextureHelper11 dest = TextureHelper11::MakeAndPossess2D(destTex, depth->getFormatSet()); + ANGLE_TRY(copyAndConvert(mResolvedDepthStencil, 0, copyBox, extents, dest, 0, copyBox, extents, + nullptr, 0, 0, 0, 8, dsDxgiInfo.pixelBytes, copyFunction)); + return dest; +} + +gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents) +{ + // Check if we need to recreate depth stencil view + if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents()) + { + return gl::NoError(); + } + + if (mResolvedDepthStencil.valid()) + { + releaseResolveDepthStencilResources(); + } + + const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps()); + + D3D11_TEXTURE2D_DESC textureDesc; + textureDesc.Width = extents.width; + textureDesc.Height = extents.height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = formatSet.texFormat; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + ID3D11Device *device = mRenderer->getDevice(); + + ID3D11Texture2D *resolvedDepthStencil = nullptr; + HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr, &resolvedDepthStencil); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate resolved depth stencil texture"); + } + d3d11::SetDebugName(resolvedDepthStencil, "Blit11::mResolvedDepthStencil"); + + ASSERT(mResolvedDepthStencilRTView == nullptr); + hr = + device->CreateRenderTargetView(resolvedDepthStencil, nullptr, &mResolvedDepthStencilRTView); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to allocate Blit11::mResolvedDepthStencilRTView"); + } + d3d11::SetDebugName(mResolvedDepthStencilRTView, "Blit11::mResolvedDepthStencilRTView"); + + mResolvedDepthStencil = TextureHelper11::MakeAndPossess2D(resolvedDepthStencil, formatSet); + + return gl::NoError(); +} + +gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(RenderTarget11 *depthStencil, + bool alsoDepth) +{ + // Multisampled depth stencil SRVs are not available in feature level 10.0 + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0) + { + return gl::Error(GL_INVALID_OPERATION, + "Resolving multisampled depth stencil textures is not supported in " + "feature level 10.0."); + } + + const auto &extents = depthStencil->getExtents(); + + ANGLE_TRY(initResolveDepthStencil(extents)); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + ID3D11Resource *stencilResource = depthStencil->getTexture(); + + // Check if we need to re-create the stencil SRV. + if (mStencilSRV) + { + ID3D11Resource *priorResource = nullptr; + mStencilSRV->GetResource(&priorResource); + + if (stencilResource != priorResource) + { + SafeRelease(mStencilSRV); + } + } + + if (!mStencilSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc; + srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet()); + srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + + HRESULT hr = device->CreateShaderResourceView(stencilResource, &srViewDesc, &mStencilSRV); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Error creating Blit11 stencil SRV"); + } + d3d11::SetDebugName(mStencilSRV, "Blit11::mStencilSRV"); + } + + // Notify the Renderer that all state should be invalidated. + mRenderer->markAllStateDirty(); + + // Apply the necessary state changes to the D3D11 immediate device context. + context->IASetInputLayout(nullptr); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0); + context->GSSetShader(nullptr, nullptr, 0); + context->RSSetState(nullptr); + context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr); + context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(extents.width); + viewport.Height = static_cast<FLOAT>(extents.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + context->RSSetViewports(1, &viewport); + + ID3D11ShaderResourceView *pixelViews[] = { + depthStencil->getShaderResourceView(), mStencilSRV, + }; + + context->PSSetShaderResources(0, 2, pixelViews); + + // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then + // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil + // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3. + if (alsoDepth) + { + context->PSSetShader(mResolveDepthStencilPS.resolve(device), nullptr, 0); + } + else + { + context->PSSetShader(mResolveStencilPS.resolve(device), nullptr, 0); + } + + // Trigger the blit on the GPU. + context->Draw(6, 0); + + gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1); + + TextureHelper11 dest; + ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, depthStencil->getFormatSet(), extents, + StagingAccess::READ_WRITE, device), + dest); + + const auto ©Function = GetCopyDepthStencilFunction(depthStencil->getInternalFormat()); + const auto &dsFormatSet = depthStencil->getFormatSet(); + const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat); + + ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents, + nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction)); + + // Return the resolved depth texture, which the caller must Release. + return dest; +} + +void Blit11::releaseResolveDepthStencilResources() +{ + SafeRelease(mStencilSRV); + SafeRelease(mResolvedDepthStencilRTView); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h new file mode 100755 index 000000000..e61f096c6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -0,0 +1,295 @@ +// +// Copyright (c) 2013 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. +// + +// Blit11.cpp: Texture copy utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include <map> + +namespace rx +{ +class Renderer11; + +class Blit11 : angle::NonCopyable +{ + public: + explicit Blit11(Renderer11 *renderer); + ~Blit11(); + + gl::Error swizzleTexture(ID3D11ShaderResourceView *source, + ID3D11RenderTargetView *dest, + const gl::Extents &size, + const gl::SwizzleState &swizzleTarget); + + gl::Error copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha); + + gl::Error copyStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::Error copyDepth(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::Error copyDepthStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::ErrorOrResult<TextureHelper11> resolveDepth(RenderTarget11 *depth); + + gl::ErrorOrResult<TextureHelper11> resolveStencil(RenderTarget11 *depthStencil, bool alsoDepth); + + using BlitConvertFunction = void(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clipRect, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData); + + private: + enum BlitShaderType + { + BLITSHADER_INVALID, + BLITSHADER_2D_RGBAF, + BLITSHADER_2D_RGBAF_PREMULTIPLY, + BLITSHADER_2D_RGBAF_UNMULTIPLY, + BLITSHADER_2D_BGRAF, + BLITSHADER_2D_BGRAF_PREMULTIPLY, + BLITSHADER_2D_BGRAF_UNMULTIPLY, + BLITSHADER_2D_RGBF, + BLITSHADER_2D_RGBF_PREMULTIPLY, + BLITSHADER_2D_RGBF_UNMULTIPLY, + BLITSHADER_2D_RGF, + BLITSHADER_2D_RF, + BLITSHADER_2D_ALPHA, + BLITSHADER_2D_LUMA, + BLITSHADER_2D_LUMAALPHA, + BLITSHADER_2D_RGBAUI, + BLITSHADER_2D_RGBAI, + BLITSHADER_2D_RGBUI, + BLITSHADER_2D_RGBI, + BLITSHADER_2D_RGUI, + BLITSHADER_2D_RGI, + BLITSHADER_2D_RUI, + BLITSHADER_2D_RI, + BLITSHADER_3D_RGBAF, + BLITSHADER_3D_RGBAUI, + BLITSHADER_3D_RGBAI, + BLITSHADER_3D_BGRAF, + BLITSHADER_3D_RGBF, + BLITSHADER_3D_RGBUI, + BLITSHADER_3D_RGBI, + BLITSHADER_3D_RGF, + BLITSHADER_3D_RGUI, + BLITSHADER_3D_RGI, + BLITSHADER_3D_RF, + BLITSHADER_3D_RUI, + BLITSHADER_3D_RI, + BLITSHADER_3D_ALPHA, + BLITSHADER_3D_LUMA, + BLITSHADER_3D_LUMAALPHA, + }; + + enum SwizzleShaderType + { + SWIZZLESHADER_INVALID, + SWIZZLESHADER_2D_FLOAT, + SWIZZLESHADER_2D_UINT, + SWIZZLESHADER_2D_INT, + SWIZZLESHADER_CUBE_FLOAT, + SWIZZLESHADER_CUBE_UINT, + SWIZZLESHADER_CUBE_INT, + SWIZZLESHADER_3D_FLOAT, + SWIZZLESHADER_3D_UINT, + SWIZZLESHADER_3D_INT, + SWIZZLESHADER_ARRAY_FLOAT, + SWIZZLESHADER_ARRAY_UINT, + SWIZZLESHADER_ARRAY_INT, + }; + + typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const gl::Box &destArea, + const gl::Extents &destSize, + void *outVertices, + unsigned int *outStride, + unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology); + + enum ShaderDimension + { + SHADER_2D, + SHADER_3D, + }; + + struct Shader + { + ShaderDimension dimension; + ID3D11PixelShader *pixelShader; + }; + + struct ShaderSupport + { + ID3D11InputLayout *inputLayout; + ID3D11VertexShader *vertexShader; + ID3D11GeometryShader *geometryShader; + WriteVertexFunction vertexWriteFunction; + }; + + gl::Error initResources(); + void freeResources(); + + ShaderSupport getShaderSupport(const Shader &shader); + + static BlitShaderType GetBlitShaderType(GLenum destinationFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension); + static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality); + + gl::Error copyDepthStencilImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + bool stencilOnly); + + gl::Error copyAndConvertImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &destStaging, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction); + + gl::Error copyAndConvert(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction); + + void addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + ID3D11PixelShader *ps); + + gl::Error getBlitShader(GLenum destFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shaderOut); + gl::Error getSwizzleShader(GLenum type, + D3D11_SRV_DIMENSION viewDimension, + const Shader **shaderOut); + + void addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + ID3D11PixelShader *ps); + + void clearShaderMap(); + void releaseResolveDepthStencilResources(); + gl::Error initResolveDepthStencil(const gl::Extents &extents); + + Renderer11 *mRenderer; + + std::map<BlitShaderType, Shader> mBlitShaderMap; + std::map<SwizzleShaderType, Shader> mSwizzleShaderMap; + + bool mResourcesInitialized; + ID3D11Buffer *mVertexBuffer; + ID3D11SamplerState *mPointSampler; + ID3D11SamplerState *mLinearSampler; + ID3D11RasterizerState *mScissorEnabledRasterizerState; + ID3D11RasterizerState *mScissorDisabledRasterizerState; + ID3D11DepthStencilState *mDepthStencilState; + + d3d11::LazyInputLayout mQuad2DIL; + d3d11::LazyShader<ID3D11VertexShader> mQuad2DVS; + d3d11::LazyShader<ID3D11PixelShader> mDepthPS; + + d3d11::LazyInputLayout mQuad3DIL; + d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS; + d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS; + + d3d11::LazyBlendState mAlphaMaskBlendState; + + ID3D11Buffer *mSwizzleCB; + + d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS; + d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS; + d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS; + d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS; + ID3D11ShaderResourceView *mStencilSRV; + TextureHelper11 mResolvedDepthStencil; + ID3D11RenderTargetView *mResolvedDepthStencilRTView; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp new file mode 100755 index 000000000..90668b759 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -0,0 +1,1556 @@ +// +// Copyright 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. +// + +// Buffer11.cpp Defines the Buffer11 class. + +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" + +#include <memory> + +#include "common/MemoryBuffer.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +namespace +{ + +template <typename T> +GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index) +{ + return reinterpret_cast<const T *>(data)[index]; +} +typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index); + +enum class CopyResult +{ + RECREATED, + NOT_RECREATED, +}; + +void CalculateConstantBufferParams(GLintptr offset, + GLsizeiptr size, + UINT *outFirstConstant, + UINT *outNumConstants) +{ + // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange). + ASSERT(offset % 256 == 0); + + // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must + // be a multiple of 16 constants. + *outFirstConstant = static_cast<UINT>(offset / 16); + + // The GL size is not required to be aligned to a 256 bytes boundary. + // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes. + *outNumConstants = static_cast<UINT>(rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16); + + // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size + // of the buffer. This behaviour is explictly allowed according to the documentation on + // ID3D11DeviceContext1::PSSetConstantBuffers1 + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx +} + +} // anonymous namespace + +namespace gl_d3d11 +{ + +D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access) +{ + bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); + + ASSERT(readBit || writeBit); + + // Note : we ignore the discard bit, because in D3D11, staging buffers + // don't accept the map-discard flag (discard only works for DYNAMIC usage) + + if (readBit && !writeBit) + { + return D3D11_MAP_READ; + } + else if (writeBit && !readBit) + { + // Special case for uniform storage - we only allow full buffer updates. + return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE; + } + else if (writeBit && readBit) + { + return D3D11_MAP_READ_WRITE; + } + else + { + UNREACHABLE(); + return D3D11_MAP_READ; + } +} +} // namespace gl_d3d11 + +// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points +// - vertex/transform feedback buffers +// - index buffers +// - pixel unpack buffers +// - uniform buffers +class Buffer11::BufferStorage : angle::NonCopyable +{ + public: + virtual ~BufferStorage() {} + + DataRevision getDataRevision() const { return mRevision; } + BufferUsage getUsage() const { return mUsage; } + size_t getSize() const { return mBufferSize; } + void setDataRevision(DataRevision rev) { mRevision = rev; } + + virtual bool isMappable(GLbitfield access) const = 0; + + virtual gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) = 0; + virtual gl::Error resize(size_t size, bool preserveData) = 0; + + virtual gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) = 0; + virtual void unmap() = 0; + + gl::Error setData(const uint8_t *data, size_t offset, size_t size); + + protected: + BufferStorage(Renderer11 *renderer, BufferUsage usage); + + Renderer11 *mRenderer; + DataRevision mRevision; + const BufferUsage mUsage; + size_t mBufferSize; +}; + +// A native buffer storage represents an underlying D3D11 buffer for a particular +// type of storage. +class Buffer11::NativeStorage : public Buffer11::BufferStorage +{ + public: + NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const angle::BroadcastChannel *onStorageChanged); + ~NativeStorage() override; + + bool isMappable(GLbitfield access) const override; + + ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } + gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; + void unmap() override; + + gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat); + + private: + static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize); + void clearSRVs(); + + ID3D11Buffer *mNativeStorage; + const angle::BroadcastChannel *mOnStorageChanged; + std::map<DXGI_FORMAT, ID3D11ShaderResourceView *> mBufferResourceViews; +}; + +// A emulated indexed buffer storage represents an underlying D3D11 buffer for data +// that has been expanded to match the indices list used. This storage is only +// used for FL9_3 pointsprite rendering emulation. +class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage +{ + public: + EmulatedIndexedStorage(Renderer11 *renderer); + ~EmulatedIndexedStorage() override; + + bool isMappable(GLbitfield access) const override { return true; } + + gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); + + gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + + gl::Error resize(size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; + void unmap() override; + + private: + ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D + MemoryBuffer mMemoryBuffer; // original data (not expanded) + MemoryBuffer mIndicesMemoryBuffer; // indices data +}; + +// Pack storage represents internal storage for pack buffers. We implement pack buffers +// as CPU memory, tied to a staging texture, for asynchronous texture readback. +class Buffer11::PackStorage : public Buffer11::BufferStorage +{ + public: + explicit PackStorage(Renderer11 *renderer); + ~PackStorage() override; + + bool isMappable(GLbitfield access) const override { return true; } + gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; + void unmap() override; + + gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms); + + private: + gl::Error flushQueuedPackCommand(); + + TextureHelper11 mStagingTexture; + MemoryBuffer mMemoryBuffer; + std::unique_ptr<PackPixelsParams> mQueuedPackCommand; + PackPixelsParams mPackParams; + bool mDataModified; +}; + +// System memory storage stores a CPU memory buffer with our buffer data. +// For dynamic data, it's much faster to update the CPU memory buffer than +// it is to update a D3D staging buffer and read it back later. +class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage +{ + public: + explicit SystemMemoryStorage(Renderer11 *renderer); + ~SystemMemoryStorage() override {} + + bool isMappable(GLbitfield access) const override { return true; } + gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; + void unmap() override; + + MemoryBuffer *getSystemCopy() { return &mSystemCopy; } + + protected: + MemoryBuffer mSystemCopy; +}; + +Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer) + : BufferD3D(state, renderer), + mRenderer(renderer), + mSize(0), + mMappedStorage(nullptr), + mBufferStorages({}), + mDeallocThresholds({}), + mIdleness({}), + mConstantBufferStorageAdditionalSize(0), + mMaxConstantBufferLruCount(0) +{ +} + +Buffer11::~Buffer11() +{ + for (auto &storage : mBufferStorages) + { + SafeDelete(storage); + } + + for (auto &p : mConstantBufferRangeStoragesCache) + { + SafeDelete(p.second.storage); + } + + mRenderer->onBufferDelete(this); +} + +gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage) +{ + updateD3DBufferUsage(usage); + ANGLE_TRY(setSubData(target, data, size, 0)); + return gl::NoError(); +} + +gl::Error Buffer11::getData(const uint8_t **outData) +{ + SystemMemoryStorage *systemMemoryStorage = nullptr; + ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage); + + ASSERT(systemMemoryStorage->getSize() >= mSize); + + *outData = systemMemoryStorage->getSystemCopy()->data(); + return gl::NoError(); +} + +gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStorage() +{ + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY), storage); + return GetAs<SystemMemoryStorage>(storage); +} + +gl::Error Buffer11::setSubData(GLenum target, const void *data, size_t size, size_t offset) +{ + size_t requiredSize = size + offset; + + if (data && size > 0) + { + // Use system memory storage for dynamic buffers. + // Try using a constant storage for constant buffers + BufferStorage *writeBuffer = nullptr; + if (target == GL_UNIFORM_BUFFER) + { + // If we are a very large uniform buffer, keep system memory storage around so that we + // aren't forced to read back from a constant buffer. We also check the workaround for + // Intel - this requires us to use system memory so we don't end up having to copy from + // a constant buffer to a staging buffer. + // TODO(jmadill): Use Context caps. + if (offset == 0 && size >= mSize && + size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) && + !mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers) + { + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), writeBuffer); + } + else + { + ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer); + } + } + else if (supportsDirectBinding()) + { + ANGLE_TRY_RESULT(getStagingStorage(), writeBuffer); + } + else + { + ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer); + } + + ASSERT(writeBuffer); + + // Explicitly resize the staging buffer, preserving data if the new data will not + // completely fill the buffer + if (writeBuffer->getSize() < requiredSize) + { + bool preserveData = (offset > 0); + ANGLE_TRY(writeBuffer->resize(requiredSize, preserveData)); + } + + writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size); + writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1); + } + + mSize = std::max(mSize, requiredSize); + invalidateStaticData(); + + return gl::NoError(); +} + +gl::Error Buffer11::copySubData(BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) +{ + Buffer11 *sourceBuffer = GetAs<Buffer11>(source); + ASSERT(sourceBuffer != nullptr); + + BufferStorage *copyDest = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(), copyDest); + + if (!copyDest) + { + ANGLE_TRY_RESULT(getStagingStorage(), copyDest); + } + + BufferStorage *copySource = nullptr; + ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(), copySource); + + if (!copySource || !copyDest) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); + } + + // If copying to/from a pixel pack buffer, we must have a staging or + // pack buffer partner, because other native buffers can't be mapped + if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable(GL_MAP_READ_BIT)) + { + ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(), copySource); + } + else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && + !copyDest->isMappable(GL_MAP_WRITE_BIT)) + { + ANGLE_TRY_RESULT(getStagingStorage(), copyDest); + } + + // D3D11 does not allow overlapped copies until 11.1, and only if the + // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap + // Get around this via a different source buffer + if (copySource == copyDest) + { + if (copySource->getUsage() == BUFFER_USAGE_STAGING) + { + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + copySource); + } + else + { + ANGLE_TRY_RESULT(getStagingStorage(), copySource); + } + } + + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset), + copyResult); + copyDest->setDataRevision(copyDest->getDataRevision() + 1); + + mSize = std::max<size_t>(mSize, destOffset + size); + invalidateStaticData(); + + return gl::NoError(); +} + +gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr) +{ + // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield + // and call mapRange. + ASSERT(access == GL_WRITE_ONLY_OES); + return mapRange(0, mSize, GL_MAP_WRITE_BIT, mapPtr); +} + +gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +{ + ASSERT(!mMappedStorage); + + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage); + + if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + { + // Latest storage is mappable. + mMappedStorage = latestStorage; + } + else + { + // Fall back to using the staging buffer if the latest storage does not exist or is not + // CPU-accessible. + ANGLE_TRY_RESULT(getStagingStorage(), mMappedStorage); + } + + if (!mMappedStorage) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); + } + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + // Update the data revision immediately, since the data might be changed at any time + mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + invalidateStaticData(); + } + + uint8_t *mappedBuffer = nullptr; + ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer)); + ASSERT(mappedBuffer); + + *mapPtr = static_cast<GLvoid *>(mappedBuffer); + return gl::NoError(); +} + +gl::Error Buffer11::unmap(GLboolean *result) +{ + ASSERT(mMappedStorage); + mMappedStorage->unmap(); + mMappedStorage = nullptr; + + // TODO: detect if we had corruption. if so, return false. + *result = GL_TRUE; + + return gl::NoError(); +} + +gl::Error Buffer11::markTransformFeedbackUsage() +{ + BufferStorage *transformFeedbackStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + transformFeedbackStorage); + + if (transformFeedbackStorage) + { + transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + } + + invalidateStaticData(); + return gl::NoError(); +} + +void Buffer11::updateDeallocThreshold(BufferUsage usage) +{ + // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/) + // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11) + + // First readback: 8 unmodified uses before we free buffer memory. + // After that, double the threshold each time until we reach the max. + if (mDeallocThresholds[usage] == 0) + { + mDeallocThresholds[usage] = 8; + } + else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u) + { + mDeallocThresholds[usage] *= 2u; + } + else + { + mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max(); + } +} + +// Free the storage if we decide it isn't being used very often. +gl::Error Buffer11::checkForDeallocation(BufferUsage usage) +{ + mIdleness[usage]++; + + BufferStorage *&storage = mBufferStorages[usage]; + if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage]) + { + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage); + if (latestStorage != storage) + { + SafeDelete(storage); + } + } + + return gl::NoError(); +} + +// Keep system memory when we are using it for the canonical version of data. +bool Buffer11::canDeallocateSystemMemory() const +{ + // Must keep system memory on Intel. + if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers) + { + return false; + } + + return (!mBufferStorages[BUFFER_USAGE_UNIFORM] || + mSize <= mRenderer->getNativeCaps().maxUniformBlockSize); +} + +void Buffer11::markBufferUsage(BufferUsage usage) +{ + mIdleness[usage] = 0; +} + +gl::Error Buffer11::garbageCollection(BufferUsage currentUsage) +{ + if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory()) + { + ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_SYSTEM_MEMORY)); + } + + if (currentUsage != BUFFER_USAGE_STAGING) + { + ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_STAGING)); + } + + return gl::NoError(); +} + +gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage) +{ + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(usage), storage); + return GetAs<NativeStorage>(storage)->getNativeStorage(); +} + +gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer( + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) +{ + ASSERT(indexInfo); + + BufferStorage *untypedStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage); + + EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage); + + ID3D11Buffer *nativeStorage = nullptr; + ANGLE_TRY_RESULT(emulatedStorage->getNativeStorage(indexInfo, attribute, startVertex), + nativeStorage); + + return nativeStorage; +} + +gl::Error Buffer11::getConstantBufferRange(GLintptr offset, + GLsizeiptr size, + ID3D11Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut) +{ + BufferStorage *bufferStorage = nullptr; + + if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets) + { + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), bufferStorage); + CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut); + } + else + { + ANGLE_TRY_RESULT(getConstantBufferRangeStorage(offset, size), bufferStorage); + *firstConstantOut = 0; + *numConstantsOut = 0; + } + + *bufferOut = GetAs<NativeStorage>(bufferStorage)->getNativeStorage(); + + return gl::NoError(); +} + +gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFormat) +{ + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage); + NativeStorage *nativeStorage = GetAs<NativeStorage>(storage); + return nativeStorage->getSRVForFormat(srvFormat); +} + +gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) +{ + PackStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getPackStorage(), packStorage); + + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage); + + ASSERT(packStorage); + ANGLE_TRY(packStorage->packPixels(readAttachment, params)); + packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); + + return gl::NoError(); +} + +size_t Buffer11::getTotalCPUBufferMemoryBytes() const +{ + size_t allocationSize = 0; + + BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING]; + allocationSize += staging ? staging->getSize() : 0; + + BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; + allocationSize += sysMem ? sysMem->getSize() : 0; + + return allocationSize; +} + +gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUsage usage) +{ + ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); + BufferStorage *&newStorage = mBufferStorages[usage]; + + if (!newStorage) + { + newStorage = allocateStorage(usage); + } + + markBufferUsage(usage); + + // resize buffer + if (newStorage->getSize() < mSize) + { + ANGLE_TRY(newStorage->resize(mSize, true)); + } + + ASSERT(newStorage); + + ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize)); + ANGLE_TRY(garbageCollection(usage)); + + return newStorage; +} + +Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) +{ + updateDeallocThreshold(usage); + switch (usage) + { + case BUFFER_USAGE_PIXEL_PACK: + return new PackStorage(mRenderer); + case BUFFER_USAGE_SYSTEM_MEMORY: + return new SystemMemoryStorage(mRenderer); + case BUFFER_USAGE_EMULATED_INDEXED_VERTEX: + return new EmulatedIndexedStorage(mRenderer); + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel); + default: + return new NativeStorage(mRenderer, usage, nullptr); + } +} + +gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeStorage( + GLintptr offset, + GLsizeiptr size) +{ + BufferStorage *newStorage; + + { + // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if + // we need to reclaim some space. + ConstantBufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset]; + + if (!cacheEntry->storage) + { + cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM); + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; + } + + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; + newStorage = cacheEntry->storage; + } + + markBufferUsage(BUFFER_USAGE_UNIFORM); + + if (newStorage->getSize() < static_cast<size_t>(size)) + { + size_t maximumAllowedAdditionalSize = 2 * getSize(); + + size_t sizeDelta = size - newStorage->getSize(); + + while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize) + { + auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache), + std::end(mConstantBufferRangeStoragesCache), + [](const ConstantBufferCache::value_type &a, + const ConstantBufferCache::value_type &b) + { + return a.second.lruCount < b.second.lruCount; + }); + + ASSERT(iter->second.storage != newStorage); + ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize()); + + mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize(); + SafeDelete(iter->second.storage); + mConstantBufferRangeStoragesCache.erase(iter); + } + + ANGLE_TRY(newStorage->resize(size, false)); + mConstantBufferStorageAdditionalSize += sizeDelta; + + // We don't copy the old data when resizing the constant buffer because the data may be + // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the + // copy. + newStorage->setDataRevision(0); + } + + ANGLE_TRY(updateBufferStorage(newStorage, offset, size)); + ANGLE_TRY(garbageCollection(BUFFER_USAGE_UNIFORM)); + return newStorage; +} + +gl::Error Buffer11::updateBufferStorage(BufferStorage *storage, + size_t sourceOffset, + size_t storageSize) +{ + BufferStorage *latestBuffer = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(), latestBuffer); + + ASSERT(storage); + + if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision()) + { + // Copy through a staging buffer if we're copying from or to a non-staging, mappable + // buffer storage. This is because we can't map a GPU buffer, and copy CPU + // data directly. If we're already using a staging buffer we're fine. + if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING && + storage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isMappable(GL_MAP_READ_BIT) || !storage->isMappable(GL_MAP_WRITE_BIT))) + { + NativeStorage *stagingBuffer = nullptr; + ANGLE_TRY_RESULT(getStagingStorage(), stagingBuffer); + + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT( + stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0), + copyResult); + stagingBuffer->setDataRevision(latestBuffer->getDataRevision()); + + latestBuffer = stagingBuffer; + } + + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0), + copyResult); + // If the D3D buffer has been recreated, we should update our serial. + if (copyResult == CopyResult::RECREATED) + { + updateSerial(); + } + storage->setDataRevision(latestBuffer->getDataRevision()); + } + + return gl::NoError(); +} + +gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getLatestBufferStorage() const +{ + // Even though we iterate over all the direct buffers, it is expected that only + // 1 or 2 will be present. + BufferStorage *latestStorage = nullptr; + DataRevision latestRevision = 0; + for (auto &storage : mBufferStorages) + { + if (storage && (!latestStorage || storage->getDataRevision() > latestRevision)) + { + latestStorage = storage; + latestRevision = storage->getDataRevision(); + } + } + + // resize buffer + if (latestStorage && latestStorage->getSize() < mSize) + { + ANGLE_TRY(latestStorage->resize(mSize, true)); + } + + return latestStorage; +} + +gl::ErrorOrResult<Buffer11::NativeStorage *> Buffer11::getStagingStorage() +{ + BufferStorage *stagingStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_STAGING), stagingStorage); + return GetAs<NativeStorage>(stagingStorage); +} + +gl::ErrorOrResult<Buffer11::PackStorage *> Buffer11::getPackStorage() +{ + BufferStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_PACK), packStorage); + return GetAs<PackStorage>(packStorage); +} + +bool Buffer11::supportsDirectBinding() const +{ + // Do not support direct buffers for dynamic data. The streaming buffer + // offers better performance for data which changes every frame. + return (mUsage == D3DBufferUsage::STATIC); +} + +void Buffer11::initializeStaticData() +{ + BufferD3D::initializeStaticData(); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(); +} + +void Buffer11::invalidateStaticData() +{ + BufferD3D::invalidateStaticData(); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(); +} + +angle::BroadcastChannel *Buffer11::getStaticBroadcastChannel() +{ + return &mStaticBroadcastChannel; +} + +angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel() +{ + return &mDirectBroadcastChannel; +} + +// Buffer11::BufferStorage implementation + +Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) +{ +} + +gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size) +{ + ASSERT(isMappable(GL_MAP_WRITE_BIT)); + + // Uniform storage can have a different internal size than the buffer size. Ensure we don't + // overflow. + size_t mapSize = std::min(size, mBufferSize - offset); + + uint8_t *writePointer = nullptr; + ANGLE_TRY(map(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer)); + + memcpy(writePointer, data, mapSize); + + unmap(); + + return gl::NoError(); +} + +// Buffer11::NativeStorage implementation + +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const angle::BroadcastChannel *onStorageChanged) + : BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged) +{ +} + +Buffer11::NativeStorage::~NativeStorage() +{ + SafeRelease(mNativeStorage); + clearSRVs(); +} + +bool Buffer11::NativeStorage::isMappable(GLbitfield access) const +{ + if ((access & GL_MAP_READ_BIT) != 0) + { + // Read is more exclusive than write mappability. + return (mUsage == BUFFER_USAGE_STAGING); + } + ASSERT((access & GL_MAP_WRITE_BIT) != 0); + return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM); +} + +// Returns true if it recreates the direct buffer +gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + size_t requiredSize = destOffset + size; + bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + + // (Re)initialize D3D buffer if needed + bool preserveData = (destOffset > 0); + if (createBuffer) + { + resize(requiredSize, preserveData); + } + + size_t clampedSize = size; + if (mUsage == BUFFER_USAGE_UNIFORM) + { + clampedSize = std::min(clampedSize, mBufferSize - destOffset); + } + + if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || + source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY) + { + ASSERT(source->isMappable(GL_MAP_READ_BIT) && isMappable(GL_MAP_WRITE_BIT)); + + // Uniform buffers must be mapped with write/discard. + ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM)); + + uint8_t *sourcePointer = nullptr; + ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer)); + + setData(sourcePointer, destOffset, clampedSize); + + source->unmap(); + } + else + { + D3D11_BOX srcBox; + srcBox.left = static_cast<unsigned int>(sourceOffset); + srcBox.right = static_cast<unsigned int>(sourceOffset + clampedSize); + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ID3D11Buffer *sourceBuffer = GetAs<NativeStorage>(source)->getNativeStorage(); + + context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0, + 0, sourceBuffer, 0, &srcBox); + } + + return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED; +} + +gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BUFFER_DESC bufferDesc; + FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size)); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", + result); + } + + d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage"); + + if (mNativeStorage && preserveData) + { + // We don't call resize if the buffer is big enough already. + ASSERT(mBufferSize <= size); + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = static_cast<unsigned int>(mBufferSize); + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); + } + + // No longer need the old buffer + SafeRelease(mNativeStorage); + mNativeStorage = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + + // Free the SRVs. + clearSRVs(); + + // Notify that the storage has changed. + if (mOnStorageChanged) + { + mOnStorageChanged->signal(); + } + + return gl::NoError(); +} + +// static +void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; + + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + + if (renderer->isES3Capable()) + { + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + } + + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // Constant buffers must be of a limited size, and aligned to 16 byte boundaries + // For our purposes we ignore any buffer data past the maximum constant buffer size + bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); + + // Note: it seems that D3D11 allows larger buffers on some platforms, but not all. + // (Windows 10 seems to allow larger constant buffers, but not Windows 7) + bufferDesc->ByteWidth = + std::min<UINT>(bufferDesc->ByteWidth, + static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize)); + break; + + default: + UNREACHABLE(); + } +} + +gl::Error Buffer11::NativeStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) +{ + ASSERT(isMappable(access)); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access); + UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + + HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map native storage in Buffer11::NativeStorage::map"); + } + ASSERT(mappedResource.pData); + *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset; + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::NativeStorage::unmap() +{ + ASSERT(isMappable(GL_MAP_WRITE_BIT) || isMappable(GL_MAP_READ_BIT)); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->Unmap(mNativeStorage, 0); +} + +gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat( + DXGI_FORMAT srvFormat) +{ + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + return bufferSRVIt->second; + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = nullptr; + + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat); + + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; + bufferSRVDesc.Buffer.ElementOffset = 0; + bufferSRVDesc.Buffer.ElementWidth = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes; + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; + + HRESULT result = device->CreateShaderResourceView(mNativeStorage, &bufferSRVDesc, &bufferSRV); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Error creating buffer SRV in Buffer11::NativeStorage::getSRVForFormat"); + } + + mBufferResourceViews[srvFormat] = bufferSRV; + + return bufferSRV; +} + +void Buffer11::NativeStorage::clearSRVs() +{ + for (auto &srv : mBufferResourceViews) + { + SafeRelease(srv.second); + } + mBufferResourceViews.clear(); +} + +// Buffer11::EmulatedIndexStorage implementation + +Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) +{ +} + +Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() +{ + SafeRelease(mNativeStorage); +} + +gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeStorage( + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) +{ + // If a change in the indices applied from the last draw call is detected, then the emulated + // indexed buffer needs to be invalidated. After invalidation, the change detected flag should + // be cleared to avoid unnecessary recreation of the buffer. + if (mNativeStorage == nullptr || indexInfo->srcIndicesChanged) + { + SafeRelease(mNativeStorage); + + // Copy the source index data. This ensures that the lifetime of the indices pointer + // stays with this storage until the next time we invalidate. + size_t indicesDataSize = 0; + switch (indexInfo->srcIndexType) + { + case GL_UNSIGNED_INT: + indicesDataSize = sizeof(GLuint) * indexInfo->srcCount; + break; + case GL_UNSIGNED_SHORT: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + case GL_UNSIGNED_BYTE: + indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount; + break; + default: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + } + + if (!mIndicesMemoryBuffer.resize(indicesDataSize)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Error resizing index memory buffer in " + "Buffer11::EmulatedIndexedStorage::getNativeStorage"); + } + + memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); + + indexInfo->srcIndicesChanged = false; + } + + if (!mNativeStorage) + { + unsigned int offset = 0; + ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset); + + // Expand the memory storage upon request and cache the results. + unsigned int expandedDataSize = + static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset); + MemoryBuffer expandedData; + if (!expandedData.resize(expandedDataSize)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getNativeStorage"); + } + + // Clear the contents of the allocated buffer + ZeroMemory(expandedData.data(), expandedDataSize); + + uint8_t *curr = expandedData.data(); + const uint8_t *ptr = static_cast<const uint8_t *>(indexInfo->srcIndices); + + // Ensure that we start in the correct place for the emulated data copy operation to + // maintain offset behaviors. + curr += offset; + + ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>; + + switch (indexInfo->srcIndexType) + { + case GL_UNSIGNED_INT: + readIndexValue = ReadIndexValueFromIndices<GLuint>; + break; + case GL_UNSIGNED_SHORT: + readIndexValue = ReadIndexValueFromIndices<GLushort>; + break; + case GL_UNSIGNED_BYTE: + readIndexValue = ReadIndexValueFromIndices<GLubyte>; + break; + } + + // Iterate over the cached index data and copy entries indicated into the emulated buffer. + for (GLuint i = 0; i < indexInfo->srcCount; i++) + { + GLuint idx = readIndexValue(ptr, i); + memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride); + curr += attribute.stride; + } + + // Finally, initialize the emulated indexed native storage object with the newly copied data + // and free the temporary buffers used. + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = expandedDataSize; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + + D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0}; + + HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Could not create emulated index data buffer: %08lX", + result); + } + d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage"); + } + + return mNativeStorage; +} + +gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage( + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ASSERT(source->isMappable(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); + ASSERT(destOffset + size <= mMemoryBuffer.size()); + memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); + source->unmap(); + return CopyResult::RECREATED; +} + +gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData) +{ + if (mMemoryBuffer.size() < size) + { + if (!mMemoryBuffer.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage"); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) +{ + ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size()); + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::EmulatedIndexedStorage::unmap() +{ + // No-op +} + +// Buffer11::PackStorage implementation + +Buffer11::PackStorage::PackStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) +{ +} + +Buffer11::PackStorage::~PackStorage() +{ +} + +gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ANGLE_TRY(flushQueuedPackCommand()); + + // For all use cases of pack buffers, we must copy through a readable buffer. + ASSERT(source->isMappable(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); + ASSERT(destOffset + size <= mMemoryBuffer.size()); + memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); + source->unmap(); + return CopyResult::NOT_RECREATED; +} + +gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData) +{ + if (size != mBufferSize) + { + if (!mMemoryBuffer.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage."); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::PackStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) +{ + ASSERT(offset + length <= getSize()); + // TODO: fast path + // We might be able to optimize out one or more memcpy calls by detecting when + // and if D3D packs the staging texture memory identically to how we would fill + // the pack buffer according to the current pack state. + + ANGLE_TRY(flushQueuedPackCommand()); + + mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); + + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::PackStorage::unmap() +{ + // No-op +} + +gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) +{ + ANGLE_TRY(flushQueuedPackCommand()); + + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(readAttachment.getRenderTarget(&renderTarget)); + + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + unsigned int srcSubresource = renderTarget->getSubresourceIndex(); + TextureHelper11 srcTexture = + TextureHelper11::MakeAndReference(renderTargetResource, renderTarget->getFormatSet()); + + mQueuedPackCommand.reset(new PackPixelsParams(params)); + + gl::Extents srcTextureSize(params.area.width, params.area.height, 1); + if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() || + mStagingTexture.getExtents() != srcTextureSize) + { + ANGLE_TRY_RESULT( + CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(), + srcTextureSize, StagingAccess::READ, mRenderer->getDevice()), + mStagingTexture); + } + + // ReadPixels from multisampled FBOs isn't supported in current GL + ASSERT(srcTexture.getSampleCount() <= 1); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + D3D11_BOX srcBox; + srcBox.left = params.area.x; + srcBox.right = params.area.x + params.area.width; + srcBox.top = params.area.y; + srcBox.bottom = params.area.y + params.area.height; + + // Select the correct layer from a 3D attachment + srcBox.front = 0; + if (mStagingTexture.getTextureType() == GL_TEXTURE_3D) + { + srcBox.front = static_cast<UINT>(readAttachment.layer()); + } + srcBox.back = srcBox.front + 1; + + // Asynchronous copy + immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0, + srcTexture.getResource(), srcSubresource, &srcBox); + + return gl::NoError(); +} + +gl::Error Buffer11::PackStorage::flushQueuedPackCommand() +{ + ASSERT(mMemoryBuffer.size() > 0); + + if (mQueuedPackCommand) + { + ANGLE_TRY( + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data())); + mQueuedPackCommand.reset(nullptr); + } + + return gl::NoError(); +} + +// Buffer11::SystemMemoryStorage implementation + +Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) + : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) +{ +} + +gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ASSERT(source->isMappable(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); + ASSERT(destOffset + size <= mSystemCopy.size()); + memcpy(mSystemCopy.data() + destOffset, sourceData, size); + source->unmap(); + return CopyResult::RECREATED; +} + +gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData) +{ + if (mSystemCopy.size() < size) + { + if (!mSystemCopy.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage"); + } + mBufferSize = size; + } + + return gl::NoError(); +} + +gl::Error Buffer11::SystemMemoryStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) +{ + ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size()); + *mapPointerOut = mSystemCopy.data() + offset; + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::SystemMemoryStorage::unmap() +{ + // No-op +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h new file mode 100755 index 000000000..3210f05bc --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -0,0 +1,156 @@ +// +// Copyright 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. +// + +// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ + +#include <array> +#include <map> + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/signal_utils.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +struct PackPixelsParams; +class Renderer11; +struct SourceIndexData; +struct TranslatedAttribute; + +// The order of this enum governs priority of 'getLatestBufferStorage'. +enum BufferUsage +{ + BUFFER_USAGE_SYSTEM_MEMORY, + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, + BUFFER_USAGE_EMULATED_INDEXED_VERTEX, + + BUFFER_USAGE_COUNT, +}; + +typedef size_t DataRevision; + +class Buffer11 : public BufferD3D +{ + public: + Buffer11(const gl::BufferState &state, Renderer11 *renderer); + virtual ~Buffer11(); + + gl::ErrorOrResult<ID3D11Buffer *> getBuffer(BufferUsage usage); + gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); + gl::Error getConstantBufferRange(GLintptr offset, + GLsizeiptr size, + ID3D11Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut); + gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRV(DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != nullptr; } + gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms); + size_t getTotalCPUBufferMemoryBytes() const; + + // BufferD3D implementation + size_t getSize() const override { return mSize; } + bool supportsDirectBinding() const override; + gl::Error getData(const uint8_t **outData) override; + void initializeStaticData() override; + void invalidateStaticData() override; + + // BufferImpl implementation + gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override; + gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override; + gl::Error copySubData(BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) override; + gl::Error map(GLenum access, GLvoid **mapPtr) override; + gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override; + gl::Error unmap(GLboolean *result) override; + gl::Error markTransformFeedbackUsage() override; + + // We use two set of dirty events. Static buffers are marked dirty whenever + // data changes, because they must be re-translated. Direct buffers only need to be + // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often. + angle::BroadcastChannel *getStaticBroadcastChannel(); + angle::BroadcastChannel *getDirectBroadcastChannel(); + + private: + class BufferStorage; + class EmulatedIndexedStorage; + class NativeStorage; + class PackStorage; + class SystemMemoryStorage; + + struct ConstantBufferCacheEntry + { + ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { } + + BufferStorage *storage; + unsigned int lruCount; + }; + + void markBufferUsage(BufferUsage usage); + gl::Error garbageCollection(BufferUsage currentUsage); + gl::ErrorOrResult<NativeStorage *> getStagingStorage(); + gl::ErrorOrResult<PackStorage *> getPackStorage(); + gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage(); + + gl::Error updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize); + gl::ErrorOrResult<BufferStorage *> getBufferStorage(BufferUsage usage); + gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage() const; + + gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(GLintptr offset, + GLsizeiptr size); + + BufferStorage *allocateStorage(BufferUsage usage); + void updateDeallocThreshold(BufferUsage usage); + + // Free the storage if we decide it isn't being used very often. + gl::Error checkForDeallocation(BufferUsage usage); + + // For some cases of uniform buffer storage, we can't deallocate system memory storage. + bool canDeallocateSystemMemory() const; + + Renderer11 *mRenderer; + size_t mSize; + + BufferStorage *mMappedStorage; + + std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages; + + // These two arrays are used to track when to free unused storage. + std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds; + std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness; + + // Cache of D3D11 constant buffer for specific ranges of buffer data. + // This is used to emulate UBO ranges on 11.0 devices. + // Constant buffers are indexed by there start offset. + typedef std::map<GLintptr /*offset*/, ConstantBufferCacheEntry> ConstantBufferCache; + ConstantBufferCache mConstantBufferRangeStoragesCache; + size_t mConstantBufferStorageAdditionalSize; + unsigned int mMaxConstantBufferLruCount; + + angle::BroadcastChannel mStaticBroadcastChannel; + angle::BroadcastChannel mDirectBroadcastChannel; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp new file mode 100755 index 000000000..f42a59ced --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -0,0 +1,672 @@ +// +// Copyright (c) 2013 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. +// + +// Clear11.cpp: Framebuffer clear utility class. + +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" + +#include <algorithm> + +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "third_party/trace_event/trace_event.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" + +namespace rx +{ + +template <typename T> +static void ApplyVertices(const gl::Extents &framebufferSize, + const gl::Rectangle *scissor, + const gl::Color<T> &color, + float depth, + void *buffer) +{ + d3d11::PositionDepthColorVertex<T> *vertices = + reinterpret_cast<d3d11::PositionDepthColorVertex<T> *>(buffer); + + float depthClear = gl::clamp01(depth); + float left = -1.0f; + float right = 1.0f; + float top = -1.0f; + float bottom = 1.0f; + + // Clip the quad coordinates to the scissor if needed + if (scissor != nullptr) + { + left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); + right = std::min( + right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); + top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / + float(framebufferSize.height)) * + 2.0f - + 1.0f); + bottom = std::min( + bottom, + ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); + } + + d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left, top, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top, depthClear, color); +} + +Clear11::ClearShader::ClearShader(DXGI_FORMAT colorType, + const char *inputLayoutName, + const BYTE *vsByteCode, + size_t vsSize, + const char *vsDebugName, + const BYTE *psByteCode, + size_t psSize, + const char *psDebugName) + : inputLayout(nullptr), + vertexShader(vsByteCode, vsSize, vsDebugName), + pixelShader(psByteCode, psSize, psDebugName) +{ + D3D11_INPUT_ELEMENT_DESC quadLayout[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, + }; + + inputLayout = new d3d11::LazyInputLayout(quadLayout, 2, vsByteCode, vsSize, inputLayoutName); +} + +Clear11::ClearShader::~ClearShader() +{ + SafeDelete(inputLayout); + vertexShader.release(); + pixelShader.release(); +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), + mClearBlendStates(StructLessThan<ClearBlendInfo>), + mFloatClearShader(nullptr), + mUintClearShader(nullptr), + mIntClearShader(nullptr), + mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>), + mVertexBuffer(nullptr), + mRasterizerState(nullptr) +{ + TRACE_EVENT0("gpu.angle", "Clear11::Clear11"); + + HRESULT result; + ID3D11Device *device = renderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + + D3D11_RASTERIZER_DESC rsDesc; + rsDesc.FillMode = D3D11_FILL_SOLID; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FrontCounterClockwise = FALSE; + rsDesc.DepthBias = 0; + rsDesc.DepthBiasClamp = 0.0f; + rsDesc.SlopeScaledDepthBias = 0.0f; + rsDesc.DepthClipEnable = TRUE; + rsDesc.ScissorEnable = FALSE; + rsDesc.MultisampleEnable = FALSE; + rsDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mFloatClearShader = + new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat, + ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat_FL9, + ArraySize(g_PS_ClearFloat_FL9), "Clear11 Float PS"); + } + else + { + mFloatClearShader = + new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat, + ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat, + ArraySize(g_PS_ClearFloat), "Clear11 Float PS"); + } + + if (renderer->isES3Capable()) + { + mUintClearShader = + new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 UINT IL", g_VS_ClearUint, + ArraySize(g_VS_ClearUint), "Clear11 UINT VS", g_PS_ClearUint, + ArraySize(g_PS_ClearUint), "Clear11 UINT PS"); + mIntClearShader = + new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 SINT IL", g_VS_ClearSint, + ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint, + ArraySize(g_PS_ClearSint), "Clear11 SINT PS"); + } +} + +Clear11::~Clear11() +{ + for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); + i++) + { + SafeRelease(i->second); + } + mClearBlendStates.clear(); + + SafeDelete(mFloatClearShader); + SafeDelete(mUintClearShader); + SafeDelete(mIntClearShader); + + for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); + i != mClearDepthStencilStates.end(); i++) + { + SafeRelease(i->second); + } + mClearDepthStencilStates.clear(); + + SafeRelease(mVertexBuffer); + SafeRelease(mRasterizerState); +} + +gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, + const gl::FramebufferState &fboData) +{ + const auto &colorAttachments = fboData.getColorAttachments(); + const auto &drawBufferStates = fboData.getDrawBufferStates(); + const auto *depthAttachment = fboData.getDepthAttachment(); + const auto *stencilAttachment = fboData.getStencilAttachment(); + + ASSERT(colorAttachments.size() == drawBufferStates.size()); + + // Iterate over the color buffers which require clearing and determine if they can be + // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. + // This requires: + // 1) The render target is being cleared to a float value (will be cast to integer when clearing + // integer + // render targets as expected but does not work the other way around) + // 2) The format of the render target has no color channels that are currently masked out. + // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special + // work. + // + // If these conditions are met, and: + // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. + // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. + // Otherwise draw a quad. + // + // Also determine if the depth stencil can be cleared with + // ID3D11DeviceContext::ClearDepthStencilView + // by checking if the stencil write mask covers the entire stencil. + // + // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex + // color + // attribute. + + gl::Extents framebufferSize; + + const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); + if (colorAttachment != nullptr) + { + framebufferSize = colorAttachment->getSize(); + } + else if (depthAttachment != nullptr) + { + framebufferSize = depthAttachment->getSize(); + } + else if (stencilAttachment != nullptr) + { + framebufferSize = stencilAttachment->getSize(); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || + clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0)) + { + // Scissor is enabled and the scissor rectangle is outside the renderbuffer + return gl::Error(GL_NO_ERROR); + } + + bool needScissoredClear = + clearParams.scissorEnabled && + (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); + + std::vector<MaskedRenderTarget> maskedClearRenderTargets; + RenderTarget11 *maskedClearDepthStencil = nullptr; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + ID3D11Device *device = mRenderer->getDevice(); + + for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); + colorAttachmentIndex++) + { + const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex]; + + if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() && + drawBufferStates[colorAttachmentIndex] != GL_NONE) + { + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment.getRenderTarget(&renderTarget)); + + const gl::InternalFormat &formatInfo = *attachment.getFormat().info; + + if (clearParams.colorClearType == GL_FLOAT && + !(formatInfo.componentType == GL_FLOAT || + formatInfo.componentType == GL_UNSIGNED_NORMALIZED || + formatInfo.componentType == GL_SIGNED_NORMALIZED)) + { + ERR("It is undefined behaviour to clear a render buffer which is not normalized " + "fixed point or floating-" + "point to floating point values (color attachment %u has internal format " + "0x%X).", + colorAttachmentIndex, attachment.getFormat().asSized()); + } + + if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && + (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && + (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && + (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) + { + // Every channel either does not exist in the render target or is masked out + continue; + } + else if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && + needScissoredClear) || + clearParams.colorClearType != GL_FLOAT || + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + // A masked clear is required, or a scissored clear is required and + // ID3D11DeviceContext1::ClearView is unavailable + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachmentIndex]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is + // possible + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Internal render target view pointer unexpectedly null."); + } + + const auto &nativeFormat = renderTarget->getFormatSet().format(); + + // Check if the actual format has a channel that the internal format does not and + // set them to the default values + float clearValues[4] = { + ((formatInfo.redBits == 0 && nativeFormat.redBits > 0) + ? 0.0f + : clearParams.colorFClearValue.red), + ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0) + ? 0.0f + : clearParams.colorFClearValue.green), + ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) + ? 0.0f + : clearParams.colorFClearValue.blue), + ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0) + ? 1.0f + : clearParams.colorFClearValue.alpha), + }; + + if (formatInfo.alphaBits == 1) + { + // Some drivers do not correctly handle calling Clear() on a format with 1-bit + // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that + // WARP does not do this. We should handle the rounding for them instead. + clearValues[3] = (clearParams.colorFClearValue.alpha >= 0.5f) ? 1.0f : 0.0f; + } + + if (needScissoredClear) + { + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + + D3D11_RECT rect; + rect.left = clearParams.scissor.x; + rect.right = clearParams.scissor.x + clearParams.scissor.width; + rect.top = clearParams.scissor.y; + rect.bottom = clearParams.scissor.y + clearParams.scissor.height; + + deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); + + if (mRenderer->getWorkarounds().callClearTwice) + { + deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); + } + } + else + { + deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + + if (mRenderer->getWorkarounds().callClearTwice) + { + deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + } + + if (clearParams.clearDepth || clearParams.clearStencil) + { + const gl::FramebufferAttachment *attachment = + (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; + ASSERT(attachment != nullptr); + + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment->getRenderTarget(&renderTarget)); + + const auto &nativeFormat = renderTarget->getFormatSet().format(); + + unsigned int stencilUnmasked = + (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0; + bool needMaskedStencilClear = + clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (needScissoredClear || needMaskedStencilClear) + { + maskedClearDepthStencil = renderTarget; + } + else + { + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Internal depth stencil view pointer unexpectedly null."); + } + + UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + + deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, + stencilClear); + } + } + + if (maskedClearRenderTargets.empty() && !maskedClearDepthStencil) + { + return gl::NoError(); + } + + // To clear the render targets and depth stencil in one pass: + // + // Render a quad clipped to the scissor rectangle which draws the clear color and a blend + // state that will perform the required color masking. + // + // The quad's depth is equal to the depth clear value with a depth stencil state that + // will enable or disable depth test/writes if the depth buffer should be cleared or not. + // + // The rasterizer state's stencil is set to always pass or fail based on if the stencil + // should be cleared or not with a stencil write mask of the stencil clear value. + // + // ====================================================================================== + // + // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- + // buffer that is not normalized fixed point or floating point with floating point values + // are undefined so we can just write floats to them and D3D11 will bit cast them to + // integers. + // + // Also, we don't have to worry about attempting to clear a normalized fixed/floating point + // buffer with integer values because there is no gl API call which would allow it, + // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to + // be a compatible clear type. + + // Bind all the render targets which need clearing + ASSERT(maskedClearRenderTargets.size() <= mRenderer->getNativeCaps().maxDrawBuffers); + std::vector<ID3D11RenderTargetView *> rtvs(maskedClearRenderTargets.size()); + for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) + { + RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; + ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); + if (!rtv) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Internal render target view pointer unexpectedly null."); + } + + rtvs[i] = rtv; + } + ID3D11DepthStencilView *dsv = + maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr; + + ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); + const FLOAT blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const UINT sampleMask = 0xFFFFFFFF; + + ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); + const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + + // Set the vertices + UINT vertexStride = 0; + const UINT startIdx = 0; + ClearShader *shader = nullptr; + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = + deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", + result); + } + + const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr; + switch (clearParams.colorClearType) + { + case GL_FLOAT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, + clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); + shader = mFloatClearShader; + break; + + case GL_UNSIGNED_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, + clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); + shader = mUintClearShader; + break; + + case GL_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, + clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); + shader = mIntClearShader; + break; + + default: + UNREACHABLE(); + break; + } + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set the viewport to be the same size as the framebuffer + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(framebufferSize.width); + viewport.Height = static_cast<FLOAT>(framebufferSize.height); + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + deviceContext->RSSetViewports(1, &viewport); + + // Apply state + deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + deviceContext->OMSetDepthStencilState(dsState, stencilClear); + deviceContext->RSSetState(mRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader->inputLayout->resolve(device)); + deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0); + deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0); + deviceContext->GSSetShader(nullptr, nullptr, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Apply render targets + mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv); + + // Draw the clear quad + deviceContext->Draw(4, 0); + + // Clean up + mRenderer->markAllStateDirty(); + + return gl::NoError(); +} + +ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget> &rts) +{ + ClearBlendInfo blendKey = {}; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + if (i < rts.size()) + { + RenderTarget11 *rt = rts[i].renderTarget; + const gl::InternalFormat &formatInfo = + gl::GetInternalFormatInfo(rt->getInternalFormat()); + + blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); + blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); + blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); + blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); + } + else + { + blendKey.maskChannels[i][0] = false; + blendKey.maskChannels[i][1] = false; + blendKey.maskChannels[i][2] = false; + blendKey.maskChannels[i][3] = false; + } + } + + ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); + if (i != mClearBlendStates.end()) + { + return i->second; + } + else + { + D3D11_BLEND_DESC blendDesc = {0}; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; + + for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++) + { + blendDesc.RenderTarget[j].BlendEnable = FALSE; + blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask( + blendKey.maskChannels[j][0], blendKey.maskChannels[j][1], + blendKey.maskChannels[j][2], blendKey.maskChannels[j][3]); + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11BlendState *blendState = nullptr; + HRESULT result = device->CreateBlendState(&blendDesc, &blendState); + if (FAILED(result) || !blendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return nullptr; + } + + mClearBlendStates[blendKey] = blendState; + + return blendState; + } +} + +ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams) +{ + ClearDepthStencilInfo dsKey = {0}; + dsKey.clearDepth = clearParams.clearDepth; + dsKey.clearStencil = clearParams.clearStencil; + dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + + ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); + if (i != mClearDepthStencilStates.end()) + { + return i->second; + } + else + { + D3D11_DEPTH_STENCIL_DESC dsDesc = {0}; + dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; + dsDesc.DepthWriteMask = + dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = dsKey.stencilWriteMask; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DepthStencilState *dsState = nullptr; + HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); + if (FAILED(result) || !dsState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return nullptr; + } + + mClearDepthStencilStates[dsKey] = dsState; + + return dsState; + } +} +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h new file mode 100755 index 000000000..1594027ec --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -0,0 +1,98 @@ +// +// Copyright (c) 2013 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. +// + +// Clear11.h: Framebuffer clear utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ + +#include <map> +#include <vector> + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ +class Renderer11; +class RenderTarget11; +struct ClearParameters; + +class Clear11 : angle::NonCopyable +{ + public: + explicit Clear11(Renderer11 *renderer); + ~Clear11(); + + // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. + gl::Error clearFramebuffer(const ClearParameters &clearParams, + const gl::FramebufferState &fboData); + + private: + struct MaskedRenderTarget + { + bool colorMask[4]; + RenderTarget11 *renderTarget; + }; + + ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts); + ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams); + + struct ClearShader final : public angle::NonCopyable + { + ClearShader(DXGI_FORMAT colorType, + const char *inputLayoutName, + const BYTE *vsByteCode, + size_t vsSize, + const char *vsDebugName, + const BYTE *psByteCode, + size_t psSize, + const char *psDebugName); + ~ClearShader(); + + d3d11::LazyInputLayout *inputLayout; + d3d11::LazyShader<ID3D11VertexShader> vertexShader; + d3d11::LazyShader<ID3D11PixelShader> pixelShader; + }; + + template <unsigned int vsSize, unsigned int psSize> + static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]); + + struct ClearBlendInfo + { + bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); + typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap; + + struct ClearDepthStencilInfo + { + bool clearDepth; + bool clearStencil; + UINT8 stencilWriteMask; + }; + typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); + typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap; + + Renderer11 *mRenderer; + + ClearBlendStateMap mClearBlendStates; + + ClearShader *mFloatClearShader; + ClearShader *mUintClearShader; + ClearShader *mIntClearShader; + + ClearDepthStencilStateMap mClearDepthStencilStates; + + ID3D11Buffer *mVertexBuffer; + ID3D11RasterizerState *mRasterizerState; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp new file mode 100755 index 000000000..05da453f0 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp @@ -0,0 +1,270 @@ +// +// Copyright 2016 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. +// +// Context11: +// D3D11-specific functionality associated with a GL Context. +// + +#include "libANGLE/renderer/d3d/d3d11/Context11.h" + +#include "common/string_utils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" + +namespace rx +{ + +Context11::Context11(const gl::ContextState &state, Renderer11 *renderer) + : ContextImpl(state), mRenderer(renderer) +{ +} + +Context11::~Context11() +{ +} + +gl::Error Context11::initialize() +{ + return gl::NoError(); +} + +CompilerImpl *Context11::createCompiler() +{ + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT); + } + else + { + return new CompilerD3D(SH_HLSL_4_1_OUTPUT); + } +} + +ShaderImpl *Context11::createShader(const gl::ShaderState &data) +{ + return new ShaderD3D(data, mRenderer->getWorkarounds()); +} + +ProgramImpl *Context11::createProgram(const gl::ProgramState &data) +{ + return new ProgramD3D(data, mRenderer); +} + +FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data) +{ + return new Framebuffer11(data, mRenderer); +} + +TextureImpl *Context11::createTexture(const gl::TextureState &state) +{ + switch (state.getTarget()) + { + case GL_TEXTURE_2D: + return new TextureD3D_2D(state, mRenderer); + case GL_TEXTURE_CUBE_MAP: + return new TextureD3D_Cube(state, mRenderer); + case GL_TEXTURE_3D: + return new TextureD3D_3D(state, mRenderer); + case GL_TEXTURE_2D_ARRAY: + return new TextureD3D_2DArray(state, mRenderer); + case GL_TEXTURE_EXTERNAL_OES: + return new TextureD3D_External(state, mRenderer); + default: + UNREACHABLE(); + } + + return nullptr; +} + +RenderbufferImpl *Context11::createRenderbuffer() +{ + return new RenderbufferD3D(mRenderer); +} + +BufferImpl *Context11::createBuffer(const gl::BufferState &state) +{ + Buffer11 *buffer = new Buffer11(state, mRenderer); + mRenderer->onBufferCreate(buffer); + return buffer; +} + +VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data) +{ + return new VertexArray11(data); +} + +QueryImpl *Context11::createQuery(GLenum type) +{ + return new Query11(mRenderer, type); +} + +FenceNVImpl *Context11::createFenceNV() +{ + return new FenceNV11(mRenderer); +} + +FenceSyncImpl *Context11::createFenceSync() +{ + return new FenceSync11(mRenderer); +} + +TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state) +{ + return new TransformFeedback11(state, mRenderer); +} + +SamplerImpl *Context11::createSampler() +{ + return new SamplerD3D(); +} + +std::vector<PathImpl *> Context11::createPaths(GLsizei) +{ + return std::vector<PathImpl *>(); +} + +gl::Error Context11::flush() +{ + return mRenderer->flush(); +} + +gl::Error Context11::finish() +{ + return mRenderer->finish(); +} + +gl::Error Context11::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + return mRenderer->genericDrawArrays(this, mode, first, count, 1); +} + +gl::Error Context11::drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount); +} + +gl::Error Context11::drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange); +} + +gl::Error Context11::drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange); +} + +gl::Error Context11::drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange); +} + +GLenum Context11::getResetStatus() +{ + return mRenderer->getResetStatus(); +} + +std::string Context11::getVendorString() const +{ + return mRenderer->getVendorString(); +} + +std::string Context11::getRendererDescription() const +{ + return mRenderer->getRendererDescription(); +} + +void Context11::insertEventMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast<size_t>(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->setMarker(optionalString.value().data()); + } +} + +void Context11::pushGroupMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast<size_t>(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->beginEvent(optionalString.value().data()); + } +} + +void Context11::popGroupMarker() +{ + mRenderer->getAnnotator()->endEvent(); +} + +void Context11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(state, dirtyBits); +} + +GLint Context11::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 Context11::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void Context11::onMakeCurrent(const gl::ContextState &data) +{ + mRenderer->getStateManager()->onMakeCurrent(data); +} + +const gl::Caps &Context11::getNativeCaps() const +{ + return mRenderer->getNativeCaps(); +} + +const gl::TextureCapsMap &Context11::getNativeTextureCaps() const +{ + return mRenderer->getNativeTextureCaps(); +} + +const gl::Extensions &Context11::getNativeExtensions() const +{ + return mRenderer->getNativeExtensions(); +} + +const gl::Limitations &Context11::getNativeLimitations() const +{ + return mRenderer->getNativeLimitations(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h new file mode 100755 index 000000000..e36a6e978 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h @@ -0,0 +1,128 @@ +// +// Copyright 2016 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. +// +// Context11: +// D3D11-specific functionality associated with a GL Context. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ + +#include "libANGLE/renderer/ContextImpl.h" + +namespace rx +{ +class Renderer11; + +class Context11 : public ContextImpl +{ + public: + Context11(const gl::ContextState &state, Renderer11 *renderer); + ~Context11() override; + + gl::Error initialize() override; + + // Shader creation + CompilerImpl *createCompiler() override; + ShaderImpl *createShader(const gl::ShaderState &data) override; + ProgramImpl *createProgram(const gl::ProgramState &data) override; + + // Framebuffer creation + FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override; + + // Texture creation + TextureImpl *createTexture(const gl::TextureState &state) override; + + // Renderbuffer creation + RenderbufferImpl *createRenderbuffer() override; + + // Buffer creation + BufferImpl *createBuffer(const gl::BufferState &state) override; + + // Vertex Array creation + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + + // Query and Fence creation + QueryImpl *createQuery(GLenum type) override; + FenceNVImpl *createFenceNV() override; + FenceSyncImpl *createFenceSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler() override; + + // Path object creation. + std::vector<PathImpl *> createPaths(GLsizei) override; + + // Flush and finish. + gl::Error flush() override; + gl::Error finish() override; + + // Drawing methods. + gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override; + gl::Error drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + gl::Error drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) override; + gl::Error drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // Debug markers. + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // State sync with dirty bits. + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::ContextState &data) override; + + // Caps queries + const gl::Caps &getNativeCaps() const override; + const gl::TextureCapsMap &getNativeTextureCaps() const override; + const gl::Extensions &getNativeExtensions() const override; + const gl::Limitations &getNativeLimitations() const override; + + Renderer11 *getRenderer() const { return mRenderer; } + + private: + Renderer11 *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp new file mode 100755 index 000000000..93343f281 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -0,0 +1,118 @@ +// +// Copyright 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. +// +// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +DebugAnnotator11::DebugAnnotator11() + : mInitialized(false), + mD3d11Module(nullptr), + mUserDefinedAnnotation(nullptr) +{ + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. +} + +DebugAnnotator11::~DebugAnnotator11() +{ + if (mInitialized) + { + SafeRelease(mUserDefinedAnnotation); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + FreeLibrary(mD3d11Module); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + } +} + +void DebugAnnotator11::beginEvent(const wchar_t *eventName) +{ + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->BeginEvent(eventName); + } +} + +void DebugAnnotator11::endEvent() +{ + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->EndEvent(); + } +} + +void DebugAnnotator11::setMarker(const wchar_t *markerName) +{ + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->SetMarker(markerName); + } +} + +bool DebugAnnotator11::getStatus() +{ +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above"); + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + return !!(mUserDefinedAnnotation->GetStatus()); + } + + return true; // Default if initializeDevice() failed +#else + // We can't detect GetStatus() on desktop ANGLE builds so always return true. + return true; +#endif // ANGLE_ENABLE_WINDOWS_STORE +} + +void DebugAnnotator11::initializeDevice() +{ + if (!mInitialized) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + ASSERT(mD3d11Module); + + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + ASSERT(D3D11CreateDevice != nullptr); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device *device = nullptr; + ID3D11DeviceContext *context = nullptr; + + HRESULT hr = E_FAIL; + + // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); + ASSERT(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context); + ASSERT(mUserDefinedAnnotation != nullptr); + mInitialized = true; + } + + SafeRelease(device); + SafeRelease(context); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h new file mode 100755 index 000000000..9da4fa220 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -0,0 +1,37 @@ +// +// Copyright 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. +// +// DebugAnnotator11.h: D3D11 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ + +#include "common/debug.h" + +namespace rx +{ + +class DebugAnnotator11 : public gl::DebugAnnotator +{ + public: + DebugAnnotator11(); + ~DebugAnnotator11() override; + void beginEvent(const wchar_t *eventName) override; + void endEvent() override; + void setMarker(const wchar_t *markerName) override; + bool getStatus() override; + + private: + void initializeDevice(); + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation *mUserDefinedAnnotation; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp new file mode 100755 index 000000000..1f0eedb6e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -0,0 +1,237 @@ +// +// Copyright (c) 2013 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. +// + +// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement +// rx::FenceNVImpl and rx::FenceSyncImpl. + +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +#include "common/utilities.h" + +namespace rx +{ + +static const int kDeviceLostCheckPeriod = 64; + +// +// Template helpers for set and test operations. +// + +template <class FenceClass> +gl::Error FenceSetHelper(FenceClass *fence) +{ + if (!fence->mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", + result); + } + } + + fence->mRenderer->getDeviceContext()->End(fence->mQuery); + return gl::Error(GL_NO_ERROR); +} + +template <class FenceClass> +gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished) +{ + ASSERT(fence->mQuery); + + UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); + HRESULT result = + fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); + } + + ASSERT(result == S_OK || result == S_FALSE); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); +} + +// +// FenceNV11 +// + +FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(NULL) +{ +} + +FenceNV11::~FenceNV11() +{ + SafeRelease(mQuery); +} + +gl::Error FenceNV11::set(GLenum condition) +{ + return FenceSetHelper(this); +} + +gl::Error FenceNV11::test(GLboolean *outFinished) +{ + return FenceTestHelper(this, true, outFinished); +} + +gl::Error FenceNV11::finish() +{ + GLboolean finished = GL_FALSE; + + int loopCount = 0; + while (finished != GL_TRUE) + { + loopCount++; + ANGLE_TRY(FenceTestHelper(this, true, &finished)); + + if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost()) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Device was lost while querying result of an event query."); + } + + ScheduleYield(); + } + + return gl::NoError(); +} + +// +// FenceSync11 +// + +// Important note on accurate timers in Windows: +// +// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call +// as timeGetTime on laptops and "jumping" during certain hardware events. +// +// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" +// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc +// +// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer +// from buggy implementations. + +FenceSync11::FenceSync11(Renderer11 *renderer) : FenceSyncImpl(), mRenderer(renderer), mQuery(NULL) +{ + LARGE_INTEGER counterFreqency = {}; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + ASSERT(success); + + mCounterFrequency = counterFreqency.QuadPart; +} + +FenceSync11::~FenceSync11() +{ + SafeRelease(mQuery); +} + +gl::Error FenceSync11::set(GLenum condition, GLbitfield flags) +{ + ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); + return FenceSetHelper(this); +} + +gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +{ + ASSERT(outResult); + + bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); + + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + + if (result == GL_TRUE) + { + *outResult = GL_ALREADY_SIGNALED; + return gl::Error(GL_NO_ERROR); + } + + if (timeout == 0) + { + *outResult = GL_TIMEOUT_EXPIRED; + return gl::Error(GL_NO_ERROR); + } + + LARGE_INTEGER currentCounter = {}; + BOOL success = QueryPerformanceCounter(¤tCounter); + ASSERT(success); + + LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + + int loopCount = 0; + while (currentCounter.QuadPart < endCounter && !result) + { + loopCount++; + ScheduleYield(); + success = QueryPerformanceCounter(¤tCounter); + ASSERT(success); + + error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + + if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost()) + { + *outResult = GL_WAIT_FAILED; + return gl::Error(GL_OUT_OF_MEMORY, + "Device was lost while querying result of an event query."); + } + } + + if (currentCounter.QuadPart >= endCounter) + { + *outResult = GL_TIMEOUT_EXPIRED; + } + else + { + *outResult = GL_CONDITION_SATISFIED; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) +{ + // Because our API is currently designed to be called from a single thread, we don't need to do + // extra work for a server-side fence. GPU commands issued after the fence is created will + // always be processed after the fence is signaled. + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::getStatus(GLint *outResult) +{ + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, false, &result); + if (error.isError()) + { + // The spec does not specify any way to report errors during the status test (e.g. device + // lost) so we report the fence is unblocked in case of error or signaled. + *outResult = GL_SIGNALED; + + return error; + } + + *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED); + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h new file mode 100755 index 000000000..595978885 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2013 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. +// + +// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" + +namespace rx +{ +class Renderer11; + +class FenceNV11 : public FenceNVImpl +{ + public: + explicit FenceNV11(Renderer11 *renderer); + ~FenceNV11() override; + + gl::Error set(GLenum condition) override; + gl::Error test(GLboolean *outFinished) override; + gl::Error finish() override; + + private: + template<class T> friend gl::Error FenceSetHelper(T *fence); + template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +class FenceSync11 : public FenceSyncImpl +{ + public: + explicit FenceSync11(Renderer11 *renderer); + ~FenceSync11() override; + + gl::Error set(GLenum condition, GLbitfield flags) override; + gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override; + gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override; + gl::Error getStatus(GLint *outResult) override; + + private: + template<class T> friend gl::Error FenceSetHelper(T *fence); + template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; + ID3D11Query *mQuery; + LONGLONG mCounterFrequency; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp new file mode 100755 index 000000000..90922914a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -0,0 +1,441 @@ +// +// Copyright 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. +// + +// Framebuffer11.cpp: Implements the Framebuffer11 class. + +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" + +#include "common/debug.h" +#include "common/BitSetIterator.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" + +using namespace angle; + +namespace rx +{ + +namespace +{ +gl::Error MarkAttachmentsDirty(const gl::FramebufferAttachment *attachment) +{ + if (attachment && attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(&texStorage)); + + if (texStorage) + { + TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage); + ASSERT(texStorage11); + + texStorage11->markLevelDirty(attachment->mipLevel()); + } + } + + return gl::NoError(); +} + +void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment, + RenderTarget11 *&cachedRenderTarget, + ChannelBinding *channelBinding) +{ + RenderTarget11 *newRenderTarget = nullptr; + if (attachment) + { + attachment->getRenderTarget(&newRenderTarget); + } + if (newRenderTarget != cachedRenderTarget) + { + auto channel = (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr); + channelBinding->bind(channel); + cachedRenderTarget = newRenderTarget; + } +} +} // anonymous namespace + +Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer), + mCachedDepthStencilRenderTarget(nullptr), + mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) +{ + ASSERT(mRenderer != nullptr); + mCachedColorRenderTargets.fill(nullptr); + for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex) + { + mColorRenderTargetsDirty.push_back( + ChannelBinding(this, static_cast<SignalToken>(colorIndex))); + } +} + +Framebuffer11::~Framebuffer11() +{ +} + +gl::Error Framebuffer11::markAttachmentsDirty() const +{ + for (const auto &colorAttachment : mState.getColorAttachments()) + { + if (colorAttachment.isAttached()) + { + ANGLE_TRY(MarkAttachmentsDirty(&colorAttachment)); + } + } + + ANGLE_TRY(MarkAttachmentsDirty(mState.getDepthAttachment())); + ANGLE_TRY(MarkAttachmentsDirty(mState.getStencilAttachment())); + + return gl::NoError(); +} + +gl::Error Framebuffer11::clearImpl(ContextImpl *context, const ClearParameters &clearParams) +{ + Clear11 *clearer = mRenderer->getClearer(); + + const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment(); + if (clearParams.scissorEnabled == true && colorAttachment != nullptr && + UsePresentPathFast(mRenderer, colorAttachment)) + { + // If the current framebuffer is using the default colorbuffer, and present path fast is + // active, and the scissor rect is enabled, then we should invert the scissor rect + // vertically + ClearParameters presentPathFastClearParams = clearParams; + gl::Extents framebufferSize = colorAttachment->getSize(); + presentPathFastClearParams.scissor.y = framebufferSize.height - + presentPathFastClearParams.scissor.y - + presentPathFastClearParams.scissor.height; + ANGLE_TRY(clearer->clearFramebuffer(presentPathFastClearParams, mState)); + } + else + { + ANGLE_TRY(clearer->clearFramebuffer(clearParams, mState)); + } + + ANGLE_TRY(markAttachmentsDirty()); + + return gl::NoError(); +} + +gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments) +{ + return invalidateBase(count, attachments, false); +} + +gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments) +{ + return invalidateBase(count, attachments, true); +} + +gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const +{ + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + + if (!deviceContext1) + { + // DiscardView() is only supported on ID3D11DeviceContext1 + return gl::NoError(); + } + + bool foundDepth = false; + bool foundStencil = false; + + for (size_t i = 0; i < count; ++i) + { + switch (attachments[i]) + { + // Handle depth and stencil attachments. Defer discarding until later. + case GL_DEPTH_STENCIL_ATTACHMENT: + foundDepth = true; + foundStencil = true; + break; + case GL_DEPTH_EXT: + case GL_DEPTH_ATTACHMENT: + foundDepth = true; + break; + case GL_STENCIL_EXT: + case GL_STENCIL_ATTACHMENT: + foundStencil = true; + break; + default: + { + // Handle color attachments + ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) || + (attachments[i] == GL_COLOR)); + + size_t colorIndex = + (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0)); + auto colorAttachment = mState.getColorAttachment(colorIndex); + if (colorAttachment) + { + ANGLE_TRY(invalidateAttachment(colorAttachment)); + } + break; + } + } + } + + bool discardDepth = false; + bool discardStencil = false; + + // The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful. + if (useEXTBehavior) + { + // In the extension, if the app discards only one of the depth and stencil attachments, but + // those are backed by the same packed_depth_stencil buffer, then both images become undefined. + discardDepth = foundDepth; + + // Don't bother discarding the stencil buffer if the depth buffer will already do it + discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr); + } + else + { + // In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the + // attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and + // STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of pixels + // of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be preserved. + discardDepth = (foundDepth && foundStencil) || + (foundDepth && (mState.getStencilAttachment() == nullptr)); + discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr)); + } + + if (discardDepth && mState.getDepthAttachment()) + { + ANGLE_TRY(invalidateAttachment(mState.getDepthAttachment())); + } + + if (discardStencil && mState.getStencilAttachment()) + { + ANGLE_TRY(invalidateAttachment(mState.getStencilAttachment())); + } + + return gl::NoError(); +} + +gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED() + return gl::NoError(); +} + +gl::Error Framebuffer11::invalidateAttachment(const gl::FramebufferAttachment *attachment) const +{ + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + ASSERT(deviceContext1); + ASSERT(attachment && attachment->isAttached()); + + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment->getRenderTarget(&renderTarget)); + ID3D11View *view = renderTarget->getRenderTargetView(); + + if (view != nullptr) + { + deviceContext1->DiscardView(view); + } + + return gl::NoError(); +} + +gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const +{ + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); + ASSERT(readAttachment); + + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != nullptr) + { + Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer); + PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack, + reinterpret_cast<ptrdiff_t>(pixels)); + + return packBufferStorage->packPixels(*readAttachment, packParams); + } + + return mRenderer->readFromAttachment(*readAttachment, area, format, type, + static_cast<GLuint>(outputPitch), pack, pixels); +} + +gl::Error Framebuffer11::blitImpl(const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = nullptr; + ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget)); + ASSERT(readRenderTarget); + + const auto &colorAttachments = mState.getColorAttachments(); + const auto &drawBufferStates = mState.getDrawBufferStates(); + + for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) + { + const gl::FramebufferAttachment &drawBuffer = colorAttachments[colorAttachment]; + + if (drawBuffer.isAttached() && + drawBufferStates[colorAttachment] != GL_NONE) + { + RenderTargetD3D *drawRenderTarget = nullptr; + ANGLE_TRY(drawBuffer.getRenderTarget(&drawRenderTarget)); + ASSERT(drawRenderTarget); + + const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer); + gl::Rectangle actualSourceArea = sourceArea; + if (invertColorSource) + { + RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget); + actualSourceArea.y = readRenderTarget11->getHeight() - sourceArea.y; + actualSourceArea.height = -sourceArea.height; + } + + const bool invertColorDest = UsePresentPathFast(mRenderer, &drawBuffer); + gl::Rectangle actualDestArea = destArea; + if (invertColorDest) + { + RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget); + actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y; + actualDestArea.height = -destArea.height; + } + + ANGLE_TRY(mRenderer->blitRenderbufferRect( + actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget, filter, + scissor, blitRenderTarget, false, false)); + } + } + } + + if (blitDepth || blitStencil) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = nullptr; + ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget)); + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTargetD3D *drawRenderTarget = nullptr; + ANGLE_TRY(drawBuffer->getRenderTarget(&drawRenderTarget)); + ASSERT(drawRenderTarget); + + ANGLE_TRY(mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, + drawRenderTarget, filter, scissor, false, + blitDepth, blitStencil)); + } + + ANGLE_TRY(markAttachmentsDirty()); + return gl::NoError(); +} + +GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget); + return renderTarget11->getFormatSet().format().fboImplementationInternalFormat; +} + +void Framebuffer11::updateColorRenderTarget(size_t colorIndex) +{ + UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex), + mCachedColorRenderTargets[colorIndex], + &mColorRenderTargetsDirty[colorIndex]); +} + +void Framebuffer11::updateDepthStencilRenderTarget() +{ + UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget, + &mDepthStencilRenderTargetDirty); +} + +void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->invalidateRenderTarget(); + + const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits; + mInternalDirtyBits.reset(); + + for (auto dirtyBit : IterateBitSet(mergedDirtyBits)) + { + switch (dirtyBit) + { + case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: + case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: + updateDepthStencilRenderTarget(); + break; + case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS: + case gl::Framebuffer::DIRTY_BIT_READ_BUFFER: + break; + default: + { + ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 && + dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX); + size_t colorIndex = + static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); + updateColorRenderTarget(colorIndex); + break; + } + } + } + + // We should not have dirtied any additional state during our sync. + ASSERT(!mInternalDirtyBits.any()); + + FramebufferD3D::syncState(dirtyBits); +} + +void Framebuffer11::signal(SignalToken token) +{ + if (token == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) + { + // Stencil is redundant in this case. + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT); + mCachedDepthStencilRenderTarget = nullptr; + } + else + { + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + token); + mCachedColorRenderTargets[token] = nullptr; + } +} + +bool Framebuffer11::hasAnyInternalDirtyBit() const +{ + return mInternalDirtyBits.any(); +} + +void Framebuffer11::syncInternalState() +{ + syncState(gl::Framebuffer::DirtyBits()); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h new file mode 100755 index 000000000..b1683a206 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -0,0 +1,88 @@ +// +// Copyright 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. +// + +// Framebuffer11.h: Defines the Framebuffer11 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/signal_utils.h" + +namespace rx +{ +class Renderer11; + +class Framebuffer11 : public FramebufferD3D, public angle::SignalReceiver +{ + public: + Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer); + virtual ~Framebuffer11(); + + gl::Error discard(size_t count, const GLenum *attachments) override; + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + + // Invalidate the cached swizzles of all bound texture attachments. + gl::Error markAttachmentsDirty() const; + + void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; + + const RenderTargetArray &getCachedColorRenderTargets() const + { + return mCachedColorRenderTargets; + } + const RenderTarget11 *getCachedDepthStencilRenderTarget() const + { + return mCachedDepthStencilRenderTarget; + } + + bool hasAnyInternalDirtyBit() const; + void syncInternalState(); + + void signal(angle::SignalToken token) override; + + private: + gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override; + + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; + + gl::Error blitImpl(const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const; + gl::Error invalidateAttachment(const gl::FramebufferAttachment *attachment) const; + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + void updateColorRenderTarget(size_t colorIndex); + void updateDepthStencilRenderTarget(); + + Renderer11 *const mRenderer; + RenderTargetArray mCachedColorRenderTargets; + RenderTarget11 *mCachedDepthStencilRenderTarget; + + std::vector<angle::ChannelBinding> mColorRenderTargetsDirty; + angle::ChannelBinding mDepthStencilRenderTargetDirty; + + gl::Framebuffer::DirtyBits mInternalDirtyBits; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp new file mode 100755 index 000000000..3c797f820 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -0,0 +1,643 @@ +// +// Copyright (c) 2012 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. +// + +// Image11.h: Implements the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#include "libANGLE/renderer/d3d/d3d11/Image11.h" + +#include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" + +namespace rx +{ + +Image11::Image11(Renderer11 *renderer) + : mRenderer(renderer), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), + mStagingTexture(NULL), + mStagingSubresource(0), + mRecoverFromStorage(false), + mAssociatedStorage(NULL), + mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), + mRecoveredFromStorageCount(0) +{ +} + +Image11::~Image11() +{ + disassociateStorage(); + releaseStagingTexture(); +} + +gl::Error Image11::generateMipmap(Image11 *dest, + Image11 *src, + const Renderer11DeviceCaps &rendererCaps) +{ + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); + + D3D11_MAPPED_SUBRESOURCE destMapped; + ANGLE_TRY(dest->map(D3D11_MAP_WRITE, &destMapped)); + + D3D11_MAPPED_SUBRESOURCE srcMapped; + gl::Error error = src->map(D3D11_MAP_READ, &srcMapped); + if (error.isError()) + { + dest->unmap(); + return error; + } + + const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData); + uint8_t *destData = reinterpret_cast<uint8_t *>(destMapped.pData); + + auto mipGenerationFunction = + d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction; + mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, + srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch, + destMapped.DepthPitch); + + dest->unmap(); + src->unmap(); + + dest->markDirty(); + + return gl::NoError(); +} + +bool Image11::isDirty() const +{ + // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be + // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new + // texture will suffice) then isDirty should still return false. + if (mDirty && !mStagingTexture && !mRecoverFromStorage) + { + const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); + const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps); + if (formatInfo.dataInitializerFunction == nullptr) + { + return false; + } + } + + return mDirty; +} + +gl::Error Image11::copyToStorage(TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) +{ + TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); + + // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage + // multiple times, then we should just keep the staging texture around to prevent the copying + // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This + // accounts for an app making a late call to glGenerateMipmap. + bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); + + if (attemptToReleaseStagingTexture) + { + // If another image is relying on this Storage for its data, then we must let it recover its + // data before we overwrite it. + ANGLE_TRY(storage11->releaseAssociatedImage(index, this)); + } + + ID3D11Resource *stagingTexture = NULL; + unsigned int stagingSubresourceIndex = 0; + ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex)); + ANGLE_TRY( + storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region)); + + // Once the image data has been copied into the Storage, we can release it locally. + if (attemptToReleaseStagingTexture) + { + storage11->associateImage(this, index); + releaseStagingTexture(); + mRecoverFromStorage = true; + mAssociatedStorage = storage11; + mAssociatedImageIndex = index; + } + + return gl::NoError(); +} + +bool Image11::isAssociatedStorageValid(TextureStorage11 *textureStorage) const +{ + return (mAssociatedStorage == textureStorage); +} + +gl::Error Image11::recoverFromAssociatedStorage() +{ + if (mRecoverFromStorage) + { + ANGLE_TRY(createStagingTexture()); + + bool textureStorageCorrect = + mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); + + // This means that the cached TextureStorage has been modified after this Image11 released + // its copy of its data. This should not have happened. The TextureStorage should have told + // this Image11 to recover its data before it was overwritten. + ASSERT(textureStorageCorrect); + + if (textureStorageCorrect) + { + // CopySubResource from the Storage to the Staging texture + gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); + ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, + mAssociatedImageIndex, region)); + mRecoveredFromStorageCount += 1; + } + + // Reset all the recovery parameters, even if the texture storage association is broken. + disassociateStorage(); + } + + return gl::NoError(); +} + +void Image11::disassociateStorage() +{ + if (mRecoverFromStorage) + { + // Make the texturestorage release the Image11 too + mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); + + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); + } +} + +bool Image11::redefine(GLenum target, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) +{ + if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat || + forceRelease) + { + // End the association with the TextureStorage, since that data will be out of date. + // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. + disassociateStorage(); + mRecoveredFromStorageCount = 0; + + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; + mInternalFormat = internalformat; + mTarget = target; + + // compute the d3d format that will be used + const d3d11::Format &formatInfo = + d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps()); + mDXGIFormat = formatInfo.texFormat; + mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + + releaseStagingTexture(); + mDirty = (formatInfo.dataInitializerFunction != NULL); + + return true; + } + + return false; +} + +DXGI_FORMAT Image11::getDXGIFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); + + return mDXGIFormat; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as +// format/type at input +// into the target pixel rectangle. +gl::Error Image11::loadData(const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum inputType, + const void *input, + bool applySkipImages) +{ + const auto sizedInputFormat = getSizedInputFormat(inputType); + const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat); + GLuint inputRowPitch = 0; + ANGLE_TRY_RESULT( + inputFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength), + inputRowPitch); + GLuint inputDepthPitch = 0; + ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch), + inputDepthPitch); + GLuint inputSkipBytes = 0; + ANGLE_TRY_RESULT( + inputFormat.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages), + inputSkipBytes); + + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + + const d3d11::Format &d3dFormatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(inputType).loadFunction; + + D3D11_MAPPED_SUBRESOURCE mappedImage; + ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage)); + + uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) + + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + + area.z * mappedImage.DepthPitch)); + loadFunction(area.width, area.height, area.depth, + reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch, + inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); + + return gl::NoError(); +} + +gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) +{ + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch); + + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; + GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; + + ASSERT(area.x % outputBlockWidth == 0); + ASSERT(area.y % outputBlockHeight == 0); + + const d3d11::Format &d3dFormatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = + d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction; + + D3D11_MAPPED_SUBRESOURCE mappedImage; + ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage)); + + uint8_t *offsetMappedData = + reinterpret_cast<uint8_t *>(mappedImage.pData) + + ((area.y / outputBlockHeight) * mappedImage.RowPitch + + (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch); + + loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t *>(input), + inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, + mappedImage.DepthPitch); + + unmap(); + + return gl::NoError(); +} + +gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) +{ + TextureStorage11 *storage11 = GetAs<TextureStorage11>(source); + + ID3D11Resource *resource = nullptr; + ANGLE_TRY(storage11->getResource(&resource)); + + UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); + TextureHelper11 textureHelper = + TextureHelper11::MakeAndReference(resource, storage11->getFormatSet()); + + gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); + return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex); +} + +gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *sourceFBO) +{ + const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer(); + ASSERT(srcAttachment); + + GLenum sourceInternalFormat = srcAttachment->getFormat().asSized(); + const auto &d3d11Format = + d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps()); + + if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat) + { + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(srcAttachment->getRenderTarget(&renderTarget)); + + RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); + ASSERT(rt11->getTexture()); + + TextureHelper11 textureHelper = + TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet()); + unsigned int sourceSubResource = rt11->getSubresourceIndex(); + + gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); + return copyWithoutConversion(destOffset, sourceBox, textureHelper, sourceSubResource); + } + + // This format requires conversion, so we must copy the texture to staging and manually convert + // via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage)); + + // determine the offset coordinate into the destination buffer + const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); + GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; + + uint8_t *dataOffset = static_cast<uint8_t *>(mappedImage.pData) + + mappedImage.RowPitch * destOffset.y + rowOffset + + destOffset.z * mappedImage.DepthPitch; + + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(mInternalFormat); + const auto &destD3D11Format = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + + auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type); + gl::Error error = gl::NoError(); + if (loadFunction.requiresConversion) + { + size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height; + MemoryBuffer *memoryBuffer = nullptr; + mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer); + GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width; + + error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format, + destFormatInfo.type, memoryBufferRowPitch, + gl::PixelPackState(), memoryBuffer->data()); + + loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(), + memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch, + mappedImage.DepthPitch); + } + else + { + error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format, + destFormatInfo.type, mappedImage.RowPitch, + gl::PixelPackState(), dataOffset); + } + + unmap(); + mDirty = true; + + return error; +} + +gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, + const gl::Box &sourceArea, + const TextureHelper11 &textureHelper, + UINT sourceSubResource) +{ + // No conversion needed-- use copyback fastpath + ID3D11Resource *stagingTexture = nullptr; + unsigned int stagingSubresourceIndex = 0; + ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex)); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + UINT subresourceAfterResolve = sourceSubResource; + + ID3D11Resource *srcTex = nullptr; + const gl::Extents &extents = textureHelper.getExtents(); + + bool needResolve = + (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1); + + if (needResolve) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = extents.width; + resolveDesc.Height = extents.height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureHelper.getFormat(); + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *srcTex2D = NULL; + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", + result); + } + srcTex = srcTex2D; + + deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(), + sourceSubResource, textureHelper.getFormat()); + subresourceAfterResolve = 0; + } + else + { + srcTex = textureHelper.getResource(); + } + + D3D11_BOX srcBox; + srcBox.left = sourceArea.x; + srcBox.right = sourceArea.x + sourceArea.width; + srcBox.top = sourceArea.y; + srcBox.bottom = sourceArea.y + sourceArea.height; + srcBox.front = sourceArea.z; + srcBox.back = sourceArea.z + sourceArea.depth; + + deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, + destOffset.y, destOffset.z, srcTex, + subresourceAfterResolve, &srcBox); + + if (needResolve) + { + SafeRelease(srcTex); + } + + mDirty = true; + return gl::NoError(); +} + +gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, + unsigned int *outSubresourceIndex) +{ + ANGLE_TRY(createStagingTexture()); + + *outStagingTexture = mStagingTexture; + *outSubresourceIndex = mStagingSubresource; + return gl::NoError(); +} + +void Image11::releaseStagingTexture() +{ + SafeRelease(mStagingTexture); +} + +gl::Error Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return gl::Error(GL_NO_ERROR); + } + + ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); + + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + int lodOffset = 1; + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); + + if (mTarget == GL_TEXTURE_3D) + { + ID3D11Texture3D *newTexture = NULL; + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()) + .dataInitializerFunction != NULL) + { + std::vector<D3D11_SUBRESOURCE_DATA> initialData; + std::vector<std::vector<BYTE>> textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, mDepth, lodOffset + 1, &initialData, + &textureData); + + result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture3D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", + result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || + mTarget == GL_TEXTURE_CUBE_MAP) + { + ID3D11Texture2D *newTexture = NULL; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()) + .dataInitializerFunction != NULL) + { + std::vector<D3D11_SUBRESOURCE_DATA> initialData; + std::vector<std::vector<BYTE>> textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, 1, lodOffset + 1, &initialData, + &textureData); + + result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture2D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", + result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else + { + UNREACHABLE(); + } + + mDirty = false; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +{ + // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. + ANGLE_TRY(recoverFromAssociatedStorage()); + + ID3D11Resource *stagingTexture = NULL; + unsigned int subresourceIndex = 0; + ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex)); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ASSERT(mStagingTexture); + HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); + + if (FAILED(result)) + { + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); + } + + mDirty = true; + + return gl::Error(GL_NO_ERROR); +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h new file mode 100755 index 000000000..17c3688b4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2012 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. +// + +// Image11.h: Defines the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ + +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/ImageIndex.h" + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; +class TextureHelper11; +class TextureStorage11; +struct Renderer11DeviceCaps; + +class Image11 : public ImageD3D +{ + public: + Image11(Renderer11 *renderer); + virtual ~Image11(); + + static gl::Error generateMipmap(Image11 *dest, + Image11 *src, + const Renderer11DeviceCaps &rendererCaps); + + virtual bool isDirty() const; + + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; + + DXGI_FORMAT getDXGIFormat() const; + + gl::Error loadData(const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) override; + gl::Error loadCompressedData(const gl::Box &area, const void *input) override; + + gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error recoverFromAssociatedStorage(); + bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + void disassociateStorage(); + + protected: + gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + void unmap(); + + private: + gl::Error copyWithoutConversion(const gl::Offset &destOffset, + const gl::Box &sourceArea, + const TextureHelper11 &textureHelper, + UINT sourceSubResource); + + gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); + gl::Error createStagingTexture(); + void releaseStagingTexture(); + + Renderer11 *mRenderer; + + DXGI_FORMAT mDXGIFormat; + ID3D11Resource *mStagingTexture; + unsigned int mStagingSubresource; + + bool mRecoverFromStorage; + TextureStorage11 *mAssociatedStorage; + gl::ImageIndex mAssociatedImageIndex; + unsigned int mRecoveredFromStorageCount; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp new file mode 100755 index 000000000..a5e78a245 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -0,0 +1,167 @@ +// +// Copyright (c) 2012 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. +// + +// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. + +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +IndexBuffer11::~IndexBuffer11() +{ + SafeRelease(mBuffer); +} + +gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mBuffer); + + updateSerial(); + + if (bufferSize > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = bufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); + } + + if (dynamic) + { + d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)"); + } + else + { + d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)"); + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamicUsage = dynamic; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + // Check for integer overflows and out-out-bounds map requests + if (offset + size < offset || offset + size > mBufferSize) + { + return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + } + + *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset; + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer11::unmapBuffer() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + return gl::Error(GL_NO_ERROR); +} + +GLenum IndexBuffer11::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error IndexBuffer11::discard() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + } + + dxContext->Unmap(mBuffer, 0); + + return gl::Error(GL_NO_ERROR); +} + +DXGI_FORMAT IndexBuffer11::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +ID3D11Buffer *IndexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h new file mode 100755 index 000000000..e730377e0 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2012 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. +// + +// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ + +#include "libANGLE/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer11; + +class IndexBuffer11 : public IndexBuffer +{ + public: + explicit IndexBuffer11(Renderer11 *const renderer); + virtual ~IndexBuffer11(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual gl::Error unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + + virtual gl::Error discard(); + + DXGI_FORMAT getIndexFormat() const; + ID3D11Buffer *getBuffer() const; + + private: + Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamicUsage; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp new file mode 100755 index 000000000..89d5dc676 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -0,0 +1,651 @@ +// +// Copyright (c) 2012 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. +// + +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +namespace +{ + +size_t GetReservedBufferCount(bool usesPointSpriteEmulation) +{ + return usesPointSpriteEmulation ? 1 : 0; +} + +gl::InputLayout GetInputLayout(const std::vector<const TranslatedAttribute *> &translatedAttributes) +{ + gl::InputLayout inputLayout(translatedAttributes.size(), gl::VERTEX_FORMAT_INVALID); + + for (size_t attributeIndex = 0; attributeIndex < translatedAttributes.size(); ++attributeIndex) + { + const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex]; + inputLayout[attributeIndex] = gl::GetVertexFormatType( + *translatedAttribute->attribute, translatedAttribute->currentValueType); + } + return inputLayout; +} + +GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, int index) +{ + // Count matrices differently + for (const sh::Attribute &attrib : shaderAttributes) + { + if (attrib.location == -1) + { + continue; + } + + GLenum transposedType = gl::TransposeMatrixType(attrib.type); + int rows = gl::VariableRowCount(transposedType); + + if (index >= attrib.location && index < attrib.location + rows) + { + return transposedType; + } + } + + UNREACHABLE(); + return GL_NONE; +} + +const unsigned int kDefaultCacheSize = 1024; + +struct PackedAttribute +{ + uint8_t attribType; + uint8_t semanticIndex; + uint8_t vertexFormatType; + uint8_t divisor; +}; + +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 : angle::IterateBitSet(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]; + } + } +} + +} // anonymous namespace + +void InputLayoutCache::PackedAttributeLayout::addAttributeData( + GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor) +{ + gl::AttributeType attribType = gl::GetAttributeType(glType); + + PackedAttribute packedAttrib; + packedAttrib.attribType = static_cast<uint8_t>(attribType); + packedAttrib.semanticIndex = static_cast<uint8_t>(semanticIndex); + packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatType); + packedAttrib.divisor = static_cast<uint8_t>(divisor); + + ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType); + ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex); + ASSERT(static_cast<gl::VertexFormatType>(packedAttrib.vertexFormatType) == vertexFormatType); + ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor); + + static_assert(sizeof(uint32_t) == sizeof(PackedAttribute), "PackedAttributes must be 32-bits exactly."); + + attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib); +} + +bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const +{ + if (numAttributes != other.numAttributes) + { + return numAttributes < other.numAttributes; + } + + if (flags != other.flags) + { + return flags < other.flags; + } + + return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0; +} + +InputLayoutCache::InputLayoutCache() + : mCurrentIL(nullptr), + mPointSpriteVertexBuffer(nullptr), + mPointSpriteIndexBuffer(nullptr), + mCacheSize(kDefaultCacheSize), + mDevice(nullptr), + mDeviceContext(nullptr) +{ + mCurrentBuffers.fill(nullptr); + mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max()); + mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max()); + mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; + mFeatureLevel = device->GetFeatureLevel(); +} + +void InputLayoutCache::clear() +{ + for (auto &layout : mLayoutMap) + { + SafeRelease(layout.second); + } + mLayoutMap.clear(); + SafeRelease(mPointSpriteVertexBuffer); + SafeRelease(mPointSpriteIndexBuffer); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = nullptr; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = nullptr; + mCurrentVertexStrides[i] = static_cast<UINT>(-1); + mCurrentVertexOffsets[i] = static_cast<UINT>(-1); + } +} + +gl::Error InputLayoutCache::applyVertexBuffers( + const gl::State &state, + const std::vector<TranslatedAttribute> &vertexArrayAttribs, + const std::vector<TranslatedAttribute> ¤tValueAttribs, + GLenum mode, + GLint start, + TranslatedIndexData *indexInfo, + GLsizei numIndicesPerInstance) +{ + ASSERT(mDevice && mDeviceContext); + + gl::Program *program = state.getProgram(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + + bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); + + AttribIndexArray sortedSemanticIndices; + SortAttributesByLayout(program, vertexArrayAttribs, currentValueAttribs, &sortedSemanticIndices, + &mCurrentAttributes); + + // If we are using FL 9_3, make sure the first attribute is not instanced + if (mFeatureLevel <= 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]); + } + } + } + + ANGLE_TRY(updateInputLayout(state, mode, sortedSemanticIndices, numIndicesPerInstance)); + + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; + + // Note that if we use instance emulation, we reserve the first buffer slot. + size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites); + + for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers); + ++attribIndex) + { + ID3D11Buffer *buffer = nullptr; + UINT vertexStride = 0; + UINT vertexOffset = 0; + + if (attribIndex < mCurrentAttributes.size()) + { + const auto &attrib = *mCurrentAttributes[attribIndex]; + Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr; + + // If indexed pointsprite emulation is active, then we need to take a less efficent code path. + // Emulated indexed pointsprite rendering requires that the vertex buffers match exactly to + // the indices passed by the caller. This could expand or shrink the vertex buffer depending + // on the number of points indicated by the index list or how many duplicates are found on the index list. + if (bufferStorage == nullptr) + { + ASSERT(attrib.vertexBuffer.get()); + buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer(); + } + else if (instancedPointSpritesActive && (indexInfo != nullptr)) + { + if (indexInfo->srcIndexData.srcBuffer != nullptr) + { + const uint8_t *bufferData = nullptr; + ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(&bufferData)); + ASSERT(bufferData != nullptr); + + ptrdiff_t offset = + reinterpret_cast<ptrdiff_t>(indexInfo->srcIndexData.srcIndices); + indexInfo->srcIndexData.srcBuffer = nullptr; + indexInfo->srcIndexData.srcIndices = bufferData + offset; + } + + ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, + attrib, start), + buffer); + } + else + { + ANGLE_TRY_RESULT( + bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), buffer); + } + + vertexStride = attrib.stride; + ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset); + } + + size_t bufferIndex = reservedBuffers + attribIndex; + + if (buffer != mCurrentBuffers[bufferIndex] || + vertexStride != mCurrentVertexStrides[bufferIndex] || + vertexOffset != mCurrentVertexOffsets[bufferIndex]) + { + dirtyBuffers = true; + minDiff = std::min(minDiff, bufferIndex); + maxDiff = std::max(maxDiff, bufferIndex); + + mCurrentBuffers[bufferIndex] = buffer; + mCurrentVertexStrides[bufferIndex] = vertexStride; + mCurrentVertexOffsets[bufferIndex] = vertexOffset; + } + } + + // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs + // to be created and added to the list of current buffers, strides and offsets collections. + // This buffer contains the vertices for a single PointSprite quad. + // An index buffer also needs to be created and applied because rendering instanced data on + // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and + // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot + // handle missing vertex data and will TDR the system. + if (programUsesInstancedPointSprites) + { + HRESULT result = S_OK; + const UINT pointSpriteVertexStride = sizeof(float) * 5; + + if (!mPointSpriteVertexBuffer) + { + static const float pointSpriteVertices[] = + { + // Position // TexCoord + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + }; + + D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 }; + D3D11_BUFFER_DESC vertexBufferDesc; + vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices); + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexBufferDesc.CPUAccessFlags = 0; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result); + } + } + + mCurrentBuffers[0] = mPointSpriteVertexBuffer; + // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid + // indexing into the vertex buffer. + mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0; + mCurrentVertexOffsets[0] = 0; + + // Update maxDiff to include the additional point sprite vertex buffer + // to ensure that IASetVertexBuffers uses the correct buffer count. + minDiff = 0; + maxDiff = std::max(maxDiff, static_cast<size_t>(0)); + + if (!mPointSpriteIndexBuffer) + { + // Create an index buffer and set it for pointsprite rendering + static const unsigned short pointSpriteIndices[] = + { + 0, 1, 2, 3, 4, 5, + }; + + D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 }; + D3D11_BUFFER_DESC indexBufferDesc; + indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices); + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer); + if (FAILED(result)) + { + SafeRelease(mPointSpriteVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result); + } + } + + if (instancedPointSpritesActive) + { + // The index buffer is applied here because Instanced PointSprite emulation uses the a + // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer() + // on the renderer will not be called and setting this buffer here ensures that the + // rendering path will contain the correct index buffers. + mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + } + } + + if (dirtyBuffers) + { + ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); + mDeviceContext->IASetVertexBuffers( + static_cast<UINT>(minDiff), static_cast<UINT>(maxDiff - minDiff + 1), + &mCurrentBuffers[minDiff], &mCurrentVertexStrides[minDiff], + &mCurrentVertexOffsets[minDiff]); + } + + return gl::NoError(); +} + +gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId) +{ + size_t reservedBuffers = GetReservedBufferCount(true); + for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex) + { + const auto &attrib = *mCurrentAttributes[attribIndex]; + size_t bufferIndex = reservedBuffers + attribIndex; + + if (attrib.divisor > 0) + { + unsigned int offset = 0; + ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset); + mCurrentVertexOffsets[bufferIndex] = + offset + (attrib.stride * (emulatedInstanceId / attrib.divisor)); + } + } + + mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers.data(), + mCurrentVertexStrides.data(), mCurrentVertexOffsets.data()); + + return gl::NoError(); +} + +gl::Error InputLayoutCache::updateInputLayout(const gl::State &state, + GLenum mode, + const AttribIndexArray &sortedSemanticIndices, + GLsizei numIndicesPerInstance) +{ + gl::Program *program = state.getProgram(); + const auto &shaderAttributes = program->getAttributes(); + PackedAttributeLayout layout; + + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + bool programUsesInstancedPointSprites = + programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); + + if (programUsesInstancedPointSprites) + { + layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES; + } + + if (instancedPointSpritesActive) + { + layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE; + } + + if (numIndicesPerInstance > 0) + { + layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE; + } + + const auto &attribs = state.getVertexArray()->getVertexAttributes(); + const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics(); + + for (unsigned long attribIndex : angle::IterateBitSet(program->getActiveAttribLocationsMask())) + { + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex); + + const auto &attrib = attribs[attribIndex]; + int d3dSemantic = locationToSemantic[attribIndex]; + + const auto ¤tValue = state.getVertexAttribCurrentValue(attribIndex); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type); + + layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, attrib.divisor); + } + + ID3D11InputLayout *inputLayout = nullptr; + if (layout.numAttributes > 0 || layout.flags != 0) + { + auto layoutMapIt = mLayoutMap.find(layout); + if (layoutMapIt != mLayoutMap.end()) + { + inputLayout = layoutMapIt->second; + } + else + { + ANGLE_TRY(createInputLayout(sortedSemanticIndices, mode, program, numIndicesPerInstance, + &inputLayout)); + if (mLayoutMap.size() >= mCacheSize) + { + TRACE("Overflowed the limit of %u input layouts, purging half the cache.", + mCacheSize); + + // Randomly release every second element + auto it = mLayoutMap.begin(); + while (it != mLayoutMap.end()) + { + it++; + if (it != mLayoutMap.end()) + { + // c++11 erase allows us to easily delete the current iterator. + SafeRelease(it->second); + it = mLayoutMap.erase(it); + } + } + } + + mLayoutMap[layout] = inputLayout; + } + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + return gl::NoError(); +} + +gl::Error InputLayoutCache::createInputLayout(const AttribIndexArray &sortedSemanticIndices, + GLenum mode, + gl::Program *program, + GLsizei numIndicesPerInstance, + ID3D11InputLayout **inputLayoutOut) +{ + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + + bool programUsesInstancedPointSprites = + programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + + unsigned int inputElementCount = 0; + std::array<D3D11_INPUT_ELEMENT_DESC, gl::MAX_VERTEX_ATTRIBS> inputElements; + + for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex) + { + const auto &attrib = *mCurrentAttributes[attribIndex]; + const int sortedIndex = sortedSemanticIndices[attribIndex]; + + D3D11_INPUT_CLASSIFICATION inputClass = + attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + + const auto &vertexFormatType = + gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType); + const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, mFeatureLevel); + + auto *inputElement = &inputElements[inputElementCount]; + + inputElement->SemanticName = "TEXCOORD"; + inputElement->SemanticIndex = sortedIndex; + inputElement->Format = vertexFormatInfo.nativeFormat; + inputElement->InputSlot = static_cast<UINT>(attribIndex); + inputElement->AlignedByteOffset = 0; + inputElement->InputSlotClass = inputClass; + inputElement->InstanceDataStepRate = attrib.divisor; + + inputElementCount++; + } + + // Instanced PointSprite emulation requires additional entries in the + // inputlayout to support the vertices that make up the pointsprite quad. + // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the + // input layout must match the shader + if (programUsesInstancedPointSprites) + { + // On 9_3, we must ensure that slot 0 contains non-instanced data. + // If slot 0 currently contains instanced data then we swap it with a non-instanced element. + // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 + // doesn't support OpenGL ES 3.0. + // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced + // simultaneously, so a non-instanced element must exist. + for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex) + { + // If rendering points and instanced pointsprite emulation is being used, the + // inputClass is required to be configured as per instance data + if (mode == GL_POINTS) + { + inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; + inputElements[elementIndex].InstanceDataStepRate = 1; + if (numIndicesPerInstance > 0 && mCurrentAttributes[elementIndex]->divisor > 0) + { + inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance; + } + } + inputElements[elementIndex].InputSlot++; + } + + inputElements[inputElementCount].SemanticName = "SPRITEPOSITION"; + inputElements[inputElementCount].SemanticIndex = 0; + inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32B32_FLOAT; + inputElements[inputElementCount].InputSlot = 0; + inputElements[inputElementCount].AlignedByteOffset = 0; + inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + inputElements[inputElementCount].InstanceDataStepRate = 0; + inputElementCount++; + + inputElements[inputElementCount].SemanticName = "SPRITETEXCOORD"; + inputElements[inputElementCount].SemanticIndex = 0; + inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32_FLOAT; + inputElements[inputElementCount].InputSlot = 0; + inputElements[inputElementCount].AlignedByteOffset = sizeof(float) * 3; + inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + inputElements[inputElementCount].InstanceDataStepRate = 0; + inputElementCount++; + } + + const gl::InputLayout &shaderInputLayout = GetInputLayout(mCurrentAttributes); + + ShaderExecutableD3D *shader = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr)); + + ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader); + + HRESULT result = + mDevice->CreateInputLayout(inputElements.data(), inputElementCount, shader11->getFunction(), + shader11->getLength(), inputLayoutOut); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal input layout, HRESULT: 0x%08x", result); + } + + return gl::NoError(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h new file mode 100755 index 000000000..62a1020f5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2012 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. +// + +// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ + +#include <GLES2/gl2.h> + +#include <cstddef> + +#include <array> +#include <map> + +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace gl +{ +class Program; +} + +namespace rx +{ +struct TranslatedAttribute; +struct TranslatedIndexData; +struct SourceIndexData; +class ProgramD3D; + +class InputLayoutCache : angle::NonCopyable +{ + public: + InputLayoutCache(); + virtual ~InputLayoutCache(); + + void initialize(ID3D11Device *device, ID3D11DeviceContext *context); + void clear(); + void markDirty(); + + gl::Error applyVertexBuffers(const gl::State &state, + const std::vector<TranslatedAttribute> &vertexArrayAttribs, + const std::vector<TranslatedAttribute> ¤tValueAttribs, + GLenum mode, + GLint start, + TranslatedIndexData *indexInfo, + GLsizei numIndicesPerInstance); + + gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId); + + // Useful for testing + void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; } + + private: + struct PackedAttributeLayout + { + PackedAttributeLayout() + : numAttributes(0), + flags(0) + { + } + + void addAttributeData(GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor); + + bool operator<(const PackedAttributeLayout &other) const; + + enum Flags + { + FLAG_USES_INSTANCED_SPRITES = 0x1, + FLAG_INSTANCED_SPRITES_ACTIVE = 0x2, + FLAG_INSTANCED_RENDERING_ACTIVE = 0x4, + }; + + size_t numAttributes; + unsigned int flags; + uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS]; + }; + + gl::Error updateInputLayout(const gl::State &state, + GLenum mode, + const AttribIndexArray &sortedSemanticIndices, + GLsizei numIndicesPerInstance); + gl::Error createInputLayout(const AttribIndexArray &sortedSemanticIndices, + GLenum mode, + gl::Program *program, + GLsizei numIndicesPerInstance, + ID3D11InputLayout **inputLayoutOut); + + std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap; + + ID3D11InputLayout *mCurrentIL; + std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentBuffers; + std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides; + std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets; + std::vector<const TranslatedAttribute *> mCurrentAttributes; + + ID3D11Buffer *mPointSpriteVertexBuffer; + ID3D11Buffer *mPointSpriteIndexBuffer; + + unsigned int mCacheSize; + + ID3D11Device *mDevice; + ID3D11DeviceContext *mDeviceContext; + D3D_FEATURE_LEVEL mFeatureLevel; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h new file mode 100755 index 000000000..4f70beddf --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11.h: Defines NativeWindow11, a class for managing and performing operations on an +// EGLNativeWindowType for the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include "libANGLE/Config.h" +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" + +namespace rx +{ + +class NativeWindow11 : public NativeWindowD3D +{ + public: + NativeWindow11(EGLNativeWindowType window) : NativeWindowD3D(window) {} + +#ifdef ANGLE_ENABLE_D3D11 + virtual HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + IDXGISwapChain **swapChain) = 0; + virtual void commitChange() = 0; +#endif +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp new file mode 100755 index 000000000..e7ca56ef2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -0,0 +1,299 @@ +// +// Copyright (c) 2013 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. +// + +// PixelTransfer11.cpp: +// Implementation for buffer-to-texture and texture-to-buffer copies. +// Used to implement pixel transfers from unpack and to pack buffers. +// + +#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/Texture.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" + +namespace rx +{ + +PixelTransfer11::PixelTransfer11(Renderer11 *renderer) + : mRenderer(renderer), + mResourcesLoaded(false), + mBufferToTextureVS(NULL), + mBufferToTextureGS(NULL), + mParamsConstantBuffer(NULL), + mCopyRasterizerState(NULL), + mCopyDepthStencilState(NULL) +{ +} + +PixelTransfer11::~PixelTransfer11() +{ + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + SafeRelease(shaderMapIt->second); + } + + mBufferToTexturePSMap.clear(); + + SafeRelease(mBufferToTextureVS); + SafeRelease(mBufferToTextureGS); + SafeRelease(mParamsConstantBuffer); + SafeRelease(mCopyRasterizerState); + SafeRelease(mCopyDepthStencilState); +} + +gl::Error PixelTransfer11::loadResources() +{ + if (mResourcesLoaded) + { + return gl::NoError(); + } + + HRESULT result = S_OK; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result); + } + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result); + } + + D3D11_BUFFER_DESC constantBufferDesc = { 0 }; + constantBufferDesc.ByteWidth = roundUp<UINT>(sizeof(CopyShaderParams), 32u); + constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDesc.MiscFlags = 0; + constantBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result); + } + d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + + // init shaders + mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); + if (!mBufferToTextureVS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); + } + + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + if (!mBufferToTextureGS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); + } + + ANGLE_TRY(buildShaderMap()); + + StructZero(&mParamsData); + + mResourcesLoaded = true; + + return gl::NoError(); +} + +void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut) +{ + StructZero(parametersOut); + + float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1); + float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1); + + unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; + unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment); + unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); + + parametersOut->FirstPixelOffset = offset / bytesPerPixel; + parametersOut->PixelsPerRow = static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width); + parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); + parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height); + parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; + parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width); + parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height); + parametersOut->FirstSlice = destArea.z; +} + +gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + ANGLE_TRY(loadResources()); + + gl::Extents destSize = destRenderTarget->getExtents(); + + ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && + destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && + destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); + + const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); + + ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); + + ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + ASSERT(pixelShader); + + // The SRV must be in the proper read format, which may be different from the destination format + // EG: for half float data, we can load full precision floats with implicit conversion + GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; + GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + + const d3d11::Format &sourceFormatInfo = + d3d11::Format::Get(sourceFormat, mRenderer->getRenderer11DeviceCaps()); + DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; + ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); + Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation()); + ID3D11ShaderResourceView *bufferSRV = nullptr; + ANGLE_TRY_RESULT(bufferStorage11->getSRV(srvFormat), bufferSRV); + ASSERT(bufferSRV != nullptr); + + ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV != nullptr); + + CopyShaderParams shaderParams; + setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Buffer *nullBuffer = nullptr; + UINT zero = 0; + + // Are we doing a 2D or 3D copy? + ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); + auto stateManager = mRenderer->getStateManager(); + + deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); + deviceContext->GSSetShader(geometryShader, NULL, 0); + deviceContext->PSSetShader(pixelShader, NULL, 0); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); + deviceContext->IASetInputLayout(NULL); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); + deviceContext->RSSetState(mCopyRasterizerState); + + stateManager->setOneTimeRenderTarget(textureRTV, nullptr); + + if (!StructEquals(mParamsData, shaderParams)) + { + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + mParamsData = shaderParams; + } + + deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(destSize.width); + viewport.Height = static_cast<FLOAT>(destSize.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + UINT numPixels = (destArea.width * destArea.height * destArea.depth); + deviceContext->Draw(numPixels, 0); + + // Unbind textures and render targets and vertex buffer + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); + + mRenderer->markAllStateDirty(); + + return gl::NoError(); +} + +gl::Error PixelTransfer11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); + mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); + + // Check that all the shaders were created successfully + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + if (shaderMapIt->second == NULL) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader."); + } + } + + return gl::NoError(); +} + +ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +{ + GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; + if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) + { + componentType = GL_FLOAT; + } + + auto shaderMapIt = mBufferToTexturePSMap.find(componentType); + return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h new file mode 100755 index 000000000..1672121ec --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 2013 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. +// + +// PixelTransfer11.h: +// Buffer-to-Texture and Texture-to-Buffer data transfers. +// Used to implement pixel unpack and pixel pack buffers in ES3. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ + +#include "libANGLE/Error.h" + +#include "common/platform.h" + +#include <GLES2/gl2.h> + +#include <map> + +namespace gl +{ + +class Buffer; +struct Box; +struct Extents; +struct PixelUnpackState; + +} + +namespace rx +{ +class Renderer11; +class RenderTargetD3D; + +class PixelTransfer11 +{ + public: + explicit PixelTransfer11(Renderer11 *renderer); + ~PixelTransfer11(); + + // unpack: the source buffer is stored in the unpack state, and buffer strides + // offset: the start of the data within the unpack buffer + // destRenderTarget: individual slice/layer of a target texture + // destinationFormat/sourcePixelsType: determines shaders + shader parameters + // destArea: the sub-section of destRenderTarget to copy to + gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + private: + + struct CopyShaderParams + { + unsigned int FirstPixelOffset; + unsigned int PixelsPerRow; + unsigned int RowStride; + unsigned int RowsPerSlice; + float PositionOffset[2]; + float PositionScale[2]; + int TexLocationOffset[2]; + int TexLocationScale[2]; + unsigned int FirstSlice; + }; + + static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); + + gl::Error loadResources(); + gl::Error buildShaderMap(); + ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + + Renderer11 *mRenderer; + + bool mResourcesLoaded; + std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap; + ID3D11VertexShader *mBufferToTextureVS; + ID3D11GeometryShader *mBufferToTextureGS; + ID3D11Buffer *mParamsConstantBuffer; + CopyShaderParams mParamsData; + + ID3D11RasterizerState *mCopyRasterizerState; + ID3D11DepthStencilState *mCopyDepthStencilState; + +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp new file mode 100755 index 000000000..58b18ded5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -0,0 +1,400 @@ +// +// Copyright (c) 2013 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. +// + +// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. + +#include "libANGLE/renderer/d3d/d3d11/Query11.h" + +#include <GLES2/gl2ext.h> + +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace +{ + +GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult) +{ + switch (type) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return currentResult + newResult; + + case GL_TIME_ELAPSED_EXT: + return currentResult + newResult; + + case GL_TIMESTAMP_EXT: + return newResult; + + case GL_COMMANDS_COMPLETED_CHROMIUM: + return newResult; + + default: + UNREACHABLE(); + return 0; + } +} + +} // anonymous namespace + +namespace rx +{ + +Query11::QueryState::QueryState() + : query(nullptr), beginTimestamp(nullptr), endTimestamp(nullptr), finished(false) +{ +} + +Query11::QueryState::~QueryState() +{ + SafeRelease(beginTimestamp); + SafeRelease(endTimestamp); + SafeRelease(query); +} + +Query11::Query11(Renderer11 *renderer, GLenum type) + : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer) +{ + mActiveQuery = std::unique_ptr<QueryState>(new QueryState()); +} + +Query11::~Query11() +{ + mRenderer->getStateManager()->onDeleteQueryObject(this); +} + +gl::Error Query11::begin() +{ + mResultSum = 0; + mRenderer->getStateManager()->onBeginQuery(this); + return resume(); +} + +gl::Error Query11::end() +{ + return pause(); +} + +gl::Error Query11::queryCounter() +{ + // This doesn't do anything for D3D11 as we don't support timestamps + ASSERT(getType() == GL_TIMESTAMP_EXT); + mResultSum = 0; + mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState())); + return gl::Error(GL_NO_ERROR); +} + +template <typename T> +gl::Error Query11::getResultBase(T *params) +{ + ASSERT(mActiveQuery->query == nullptr); + ANGLE_TRY(flush(true)); + ASSERT(mPendingQueries.empty()); + *params = static_cast<T>(mResultSum); + + return gl::NoError(); +} + +gl::Error Query11::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::isResultAvailable(bool *available) +{ + ANGLE_TRY(flush(false)); + + *available = mPendingQueries.empty(); + return gl::NoError(); +} + +gl::Error Query11::pause() +{ + if (mActiveQuery->query != nullptr) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + GLenum queryType = getType(); + + // If we are doing time elapsed query the end timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + context->End(mActiveQuery->endTimestamp); + } + + context->End(mActiveQuery->query); + + mPendingQueries.push_back(std::move(mActiveQuery)); + mActiveQuery = std::unique_ptr<QueryState>(new QueryState()); + } + + return flush(false); +} + +gl::Error Query11::resume() +{ + if (mActiveQuery->query == nullptr) + { + ANGLE_TRY(flush(false)); + + GLenum queryType = getType(); + D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType); + + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = d3dQueryType; + queryDesc.MiscFlags = 0; + + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT result = device->CreateQuery(&queryDesc, &mActiveQuery->query); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", + result); + } + + // If we are doing time elapsed we also need a query to actually query the timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + D3D11_QUERY_DESC desc; + desc.Query = D3D11_QUERY_TIMESTAMP; + desc.MiscFlags = 0; + result = device->CreateQuery(&desc, &mActiveQuery->beginTimestamp); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", + result); + } + result = device->CreateQuery(&desc, &mActiveQuery->endTimestamp); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", + result); + } + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + if (d3dQueryType != D3D11_QUERY_EVENT) + { + context->Begin(mActiveQuery->query); + } + + // If we are doing time elapsed, query the begin timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + context->End(mActiveQuery->beginTimestamp); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query11::flush(bool force) +{ + while (!mPendingQueries.empty()) + { + QueryState *query = mPendingQueries.front().get(); + + do + { + ANGLE_TRY(testQuery(query)); + if (!query->finished && !force) + { + return gl::Error(GL_NO_ERROR); + } + } while (!query->finished); + + mResultSum = MergeQueryResults(getType(), mResultSum, mResult); + mPendingQueries.pop_front(); + } + + return gl::NoError(); +} + +gl::Error Query11::testQuery(QueryState *queryState) +{ + if (!queryState->finished) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + { + ASSERT(queryState->query); + UINT64 numPixels = 0; + HRESULT result = + context->GetData(queryState->query, &numPixels, sizeof(numPixels), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", + result); + } + + if (result == S_OK) + { + queryState->finished = true; + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + } + } + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + { + ASSERT(queryState->query); + D3D11_QUERY_DATA_SO_STATISTICS soStats = {0}; + HRESULT result = context->GetData(queryState->query, &soStats, sizeof(soStats), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", + result); + } + + if (result == S_OK) + { + queryState->finished = true; + mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten); + } + } + break; + + case GL_TIME_ELAPSED_EXT: + { + ASSERT(queryState->query); + ASSERT(queryState->beginTimestamp); + ASSERT(queryState->endTimestamp); + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0}; + HRESULT result = + context->GetData(queryState->query, &timeStats, sizeof(timeStats), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", + result); + } + + if (result == S_OK) + { + UINT64 beginTime = 0; + HRESULT beginRes = + context->GetData(queryState->beginTimestamp, &beginTime, sizeof(UINT64), 0); + if (FAILED(beginRes)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", beginRes); + } + UINT64 endTime = 0; + HRESULT endRes = + context->GetData(queryState->endTimestamp, &endTime, sizeof(UINT64), 0); + if (FAILED(endRes)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", endRes); + } + + if (beginRes == S_OK && endRes == S_OK) + { + queryState->finished = true; + if (timeStats.Disjoint) + { + mRenderer->setGPUDisjoint(); + } + static_assert(sizeof(UINT64) == sizeof(unsigned long long), + "D3D UINT64 isn't 64 bits"); + + angle::CheckedNumeric<UINT64> checkedTime(endTime); + checkedTime -= beginTime; + checkedTime *= 1000000000ull; + checkedTime /= timeStats.Frequency; + if (checkedTime.IsValid()) + { + mResult = checkedTime.ValueOrDie(); + } + else + { + mResult = std::numeric_limits<GLuint64>::max() / timeStats.Frequency; + // If an overflow does somehow occur, there is no way the elapsed time + // is accurate, so we generate a disjoint event + mRenderer->setGPUDisjoint(); + } + } + } + } + break; + + case GL_TIMESTAMP_EXT: + { + // D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed + // to have any sort of continuity outside of a disjoint timestamp query block, which + // GL depends on + ASSERT(queryState->query == nullptr); + mResult = 0; + queryState->finished = true; + } + break; + + case GL_COMMANDS_COMPLETED_CHROMIUM: + { + ASSERT(queryState->query); + BOOL completed = 0; + HRESULT result = + context->GetData(queryState->query, &completed, sizeof(completed), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", + result); + } + + if (result == S_OK) + { + queryState->finished = true; + ASSERT(completed == TRUE); + mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; + } + } + break; + + default: + UNREACHABLE(); + break; + } + + if (!queryState->finished && mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + } + + return gl::NoError(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h new file mode 100755 index 000000000..706f805df --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h @@ -0,0 +1,67 @@ +// +// Copyright (c) 2013 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. +// + +// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ + +#include <deque> + +#include "libANGLE/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer11; + +class Query11 : public QueryImpl +{ + public: + Query11(Renderer11 *renderer, GLenum type); + ~Query11() override; + + gl::Error begin() override; + gl::Error end() override; + gl::Error queryCounter() override; + gl::Error getResult(GLint *params) override; + gl::Error getResult(GLuint *params) override; + gl::Error getResult(GLint64 *params) override; + gl::Error getResult(GLuint64 *params) override; + gl::Error isResultAvailable(bool *available) override; + + gl::Error pause(); + gl::Error resume(); + + private: + struct QueryState final : public angle::NonCopyable + { + QueryState(); + ~QueryState(); + + ID3D11Query *query; + ID3D11Query *beginTimestamp; + ID3D11Query *endTimestamp; + bool finished; + }; + + gl::Error flush(bool force); + gl::Error testQuery(QueryState *queryState); + + template <typename T> + gl::Error getResultBase(T *params); + + GLuint64 mResult; + GLuint64 mResultSum; + + Renderer11 *mRenderer; + + std::unique_ptr<QueryState> mActiveQuery; + std::deque<std::unique_ptr<QueryState>> mPendingQueries; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp new file mode 100755 index 000000000..bd870bcbd --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -0,0 +1,473 @@ +// +// 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. +// + +// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" + +#include <float.h> + +#include "common/debug.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ +using namespace gl_d3d11; + +template <typename mapType> +static void ClearStateMap(mapType &map) +{ + for (typename mapType::iterator i = map.begin(); i != map.end(); i++) + { + SafeRelease(i->second.first); + } + map.clear(); +} + +// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, +// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum +// number of unique states of each type an application can create is 4096 +const unsigned int RenderStateCache::kMaxBlendStates = 4096; +const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; +const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; +const unsigned int RenderStateCache::kMaxSamplerStates = 4096; + +RenderStateCache::RenderStateCache(Renderer11 *renderer) + : mRenderer(renderer), + mCounter(0), + mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), + mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), + mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates), + mDevice(NULL) +{ +} + +RenderStateCache::~RenderStateCache() +{ + clear(); +} + +void RenderStateCache::initialize(ID3D11Device *device) +{ + clear(); + mDevice = device; +} + +void RenderStateCache::clear() +{ + ClearStateMap(mBlendStateCache); + ClearStateMap(mRasterizerStateCache); + ClearStateMap(mDepthStencilStateCache); + ClearStateMap(mSamplerStateCache); +} + +std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; +} + +gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, + ID3D11BlendState **outBlendState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + bool mrt = false; + + const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(); + + BlendStateKey key = {}; + key.blendState = blendState; + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment]; + + auto rtChannels = key.rtChannels[colorAttachment]; + + if (attachment) + { + if (colorAttachment > 0) + { + mrt = true; + } + + rtChannels[0] = attachment->getRedSize() > 0; + rtChannels[1] = attachment->getGreenSize() > 0; + rtChannels[2] = attachment->getBlueSize() > 0; + rtChannels[3] = attachment->getAlphaSize() > 0; + } + } + + BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + if (keyIter != mBlendStateCache.end()) + { + BlendStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outBlendState = state.first; + return gl::Error(GL_NO_ERROR); + } + else + { + if (mBlendStateCache.size() >= kMaxBlendStates) + { + TRACE("Overflowed the limit of %u blend states, removing the least recently used " + "to make room.", kMaxBlendStates); + + BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mBlendStateCache.erase(leastRecentlyUsed); + } + + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; + + rtBlend.BlendEnable = blendState.blend; + if (blendState.blend) + { + rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + + rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); + } + + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, + key.rtChannels[i][1] && blendState.colorMaskGreen, + key.rtChannels[i][2] && blendState.colorMaskBlue, + key.rtChannels[i][3] && blendState.colorMaskAlpha); + } + + ID3D11BlendState *dx11BlendState = NULL; + HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); + if (FAILED(result) || !dx11BlendState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + } + + mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + + *outBlendState = dx11BlendState; + return gl::Error(GL_NO_ERROR); + } +} + +std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); + return hash; +} + +bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + RasterizerStateKey key = {}; + key.rasterizerState = rasterState; + key.scissorEnabled = scissorEnabled; + + RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + if (keyIter != mRasterizerStateCache.end()) + { + RasterizerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outRasterizerState = state.first; + return gl::Error(GL_NO_ERROR); + } + else + { + if (mRasterizerStateCache.size() >= kMaxRasterizerStates) + { + TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " + "to make room.", kMaxRasterizerStates); + + RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mRasterizerStateCache.erase(leastRecentlyUsed); + } + + D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); + + // Disable culling if drawing points + if (rasterState.pointDrawMode) + { + cullMode = D3D11_CULL_NONE; + } + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = cullMode; + rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; + rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + if (rasterState.polygonOffsetFill) + { + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; + } + else + { + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; + } + + ID3D11RasterizerState *dx11RasterizerState = NULL; + HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); + if (FAILED(result) || !dx11RasterizerState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); + } + + mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); + + *outRasterizerState = dx11RasterizerState; + return gl::Error(GL_NO_ERROR); + } +} + +std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) +{ + return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; +} + +gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + gl::DepthStencilState glState = originalState; + if (disableDepth) + { + glState.depthTest = false; + glState.depthMask = false; + } + + if (disableStencil) + { + glState.stencilWritemask = 0; + glState.stencilBackWritemask = 0; + glState.stencilTest = false; + } + + auto keyIter = mDepthStencilStateCache.find(glState); + if (keyIter != mDepthStencilStateCache.end()) + { + DepthStencilStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outDSState = state.first; + return gl::Error(GL_NO_ERROR); + } + + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) + { + TRACE( + "Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", + kMaxDepthStencilStates); + + auto leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } + + D3D11_DEPTH_STENCIL_DESC dsDesc = {0}; + dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask); + dsDesc.DepthFunc = ConvertComparison(glState.depthFunc); + dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask); + dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc); + dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + } + + mDepthStencilStateCache.insert( + std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++))); + + *outDSState = dx11DepthStencilState; + return gl::Error(GL_NO_ERROR); +} + +std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) +{ + return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; +} + +gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); + if (keyIter != mSamplerStateCache.end()) + { + SamplerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outSamplerState = state.first; + return gl::Error(GL_NO_ERROR); + } + else + { + if (mSamplerStateCache.size() >= kMaxSamplerStates) + { + TRACE("Overflowed the limit of %u sampler states, removing the least recently used " + "to make room.", kMaxSamplerStates); + + SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mSamplerStateCache.erase(leastRecentlyUsed); + } + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, + samplerState.maxAnisotropy, samplerState.compareMode); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = + gl_d3d11::ConvertMaxAnisotropy(samplerState.maxAnisotropy, mDevice->GetFeatureLevel()); + samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = samplerState.minLod; + samplerDesc.MaxLOD = samplerState.maxLod; + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX. + // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves. + ASSERT(samplerState.maxLod >= 999.9f); + + // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this. + samplerDesc.MaxLOD = FLT_MAX; + } + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); + if (FAILED(result) || !dx11SamplerState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result); + } + + mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); + + *outSamplerState = dx11SamplerState; + return gl::Error(GL_NO_ERROR); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h new file mode 100755 index 000000000..82cb13903 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -0,0 +1,114 @@ +// +// 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. +// + +// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "common/angleutils.h" + +#include <unordered_map> + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; + +class RenderStateCache : angle::NonCopyable +{ + public: + RenderStateCache(Renderer11 *renderer); + virtual ~RenderStateCache(); + + void initialize(ID3D11Device *device); + void clear(); + + gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState); + gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState); + gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); + + private: + Renderer11 *mRenderer; + unsigned long long mCounter; + + // Blend state cache + struct BlendStateKey + { + gl::BlendState blendState; + bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + static std::size_t hashBlendState(const BlendStateKey &blendState); + static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); + static const unsigned int kMaxBlendStates; + + typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); + typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); + typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair; + typedef std::unordered_map<BlendStateKey, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap; + BlendStateMap mBlendStateCache; + + // Rasterizer state cache + struct RasterizerStateKey + { + gl::RasterizerState rasterizerState; + bool scissorEnabled; + }; + static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); + static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); + static const unsigned int kMaxRasterizerStates; + + typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); + typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); + typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair; + typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap; + RasterizerStateMap mRasterizerStateCache; + + // Depth stencil state cache + static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); + static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); + static const unsigned int kMaxDepthStencilStates; + + typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); + typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); + typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair; + typedef std::unordered_map<gl::DepthStencilState, + DepthStencilStateCounterPair, + DepthStencilStateHashFunction, + DepthStencilStateEqualityFunction> DepthStencilStateMap; + DepthStencilStateMap mDepthStencilStateCache; + + // Sample state cache + static std::size_t hashSamplerState(const gl::SamplerState &samplerState); + static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); + static const unsigned int kMaxSamplerStates; + + typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); + typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); + typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair; + typedef std::unordered_map<gl::SamplerState, + SamplerStateCounterPair, + SamplerStateHashFunction, + SamplerStateEqualityFunction> SamplerStateMap; + SamplerStateMap mSamplerStateCache; + + ID3D11Device *mDevice; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp new file mode 100755 index 000000000..a042f447d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -0,0 +1,444 @@ +// +// Copyright (c) 2012 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. +// + +// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +namespace rx +{ + +namespace +{ +bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +{ + ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource); + if (texture1D) + { + D3D11_TEXTURE1D_DESC texDesc; + texture1D->GetDesc(&texDesc); + SafeRelease(texture1D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); + if (texture2D) + { + D3D11_TEXTURE2D_DESC texDesc; + texture2D->GetDesc(&texDesc); + SafeRelease(texture2D); + + *mipLevels = texDesc.MipLevels; + *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; + + return true; + } + + ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource); + if (texture3D) + { + D3D11_TEXTURE3D_DESC texDesc; + texture3D->GetDesc(&texDesc); + SafeRelease(texture3D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + return false; +} + +unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) +{ + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + view->GetDesc(&rtvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + switch (rtvDesc.ViewDimension) + { + case D3D11_RTV_DIMENSION_TEXTURE1D: + mipSlice = rtvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + mipSlice = rtvDesc.Texture1DArray.MipSlice; + arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + mipSlice = rtvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + mipSlice = rtvDesc.Texture2DArray.MipSlice; + arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + mipSlice = rtvDesc.Texture3D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_RTV_DIMENSION_BUFFER: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + unsigned int mipLevels, samples; + GetTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) +{ + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + view->GetDesc(&dsvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + switch (dsvDesc.ViewDimension) + { + case D3D11_DSV_DIMENSION_TEXTURE1D: + mipSlice = dsvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + mipSlice = dsvDesc.Texture1DArray.MipSlice; + arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + mipSlice = dsvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + mipSlice = dsvDesc.Texture2DArray.MipSlice; + arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + unsigned int mipLevels, samples; + GetTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +GLenum GetSurfaceRTFormat(bool depth, SwapChain11 *swapChain) +{ + return (depth ? swapChain->getDepthBufferInternalFormat() + : swapChain->getRenderTargetInternalFormat()); +} + +const d3d11::Format &GetSurfaceFormatSet(bool depth, SwapChain11 *swapChain, Renderer11 *renderer) +{ + return d3d11::Format::Get(GetSurfaceRTFormat(depth, swapChain), + renderer->getRenderer11DeviceCaps()); +} + +} // anonymous namespace + +RenderTarget11::RenderTarget11(const d3d11::Format &formatSet) : mFormatSet(formatSet) +{ +} + +RenderTarget11::~RenderTarget11() +{ + signalDirty(); +} + +void RenderTarget11::signalDirty() +{ + mBroadcastChannel.signal(); + + // Clear the list. We can't do this in the receiver because it would mutate during iteration. + mBroadcastChannel.reset(); +} + +TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, + ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, + ID3D11ShaderResourceView *blitSRV, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples) + : RenderTarget11(formatSet), + mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(rtv), + mDepthStencil(NULL), + mShaderResource(srv), + mBlitShaderResource(blitSRV) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mBlitShaderResource) + { + mBlitShaderResource->AddRef(); + } + + if (mRenderTarget && mTexture) + { + mSubresourceIndex = GetRTVSubresourceIndex(mTexture, mRenderTarget); + } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); +} + +TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, + ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples) + : RenderTarget11(formatSet), + mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(NULL), + mDepthStencil(dsv), + mShaderResource(srv), + mBlitShaderResource(nullptr) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mDepthStencil && mTexture) + { + mSubresourceIndex = GetDSVSubresourceIndex(mTexture, mDepthStencil); + } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); +} + +TextureRenderTarget11::~TextureRenderTarget11() +{ + SafeRelease(mTexture); + SafeRelease(mRenderTarget); + SafeRelease(mDepthStencil); + SafeRelease(mShaderResource); + SafeRelease(mBlitShaderResource); +} + +ID3D11Resource *TextureRenderTarget11::getTexture() const +{ + return mTexture; +} + +ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const +{ + return mRenderTarget; +} + +ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const +{ + return mDepthStencil; +} + +ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const +{ + return mShaderResource; +} + +ID3D11ShaderResourceView *TextureRenderTarget11::getBlitShaderResourceView() const +{ + return mBlitShaderResource; +} + +GLsizei TextureRenderTarget11::getWidth() const +{ + return mWidth; +} + +GLsizei TextureRenderTarget11::getHeight() const +{ + return mHeight; +} + +GLsizei TextureRenderTarget11::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget11::getInternalFormat() const +{ + return mInternalFormat; +} + +GLsizei TextureRenderTarget11::getSamples() const +{ + return mSamples; +} + +unsigned int TextureRenderTarget11::getSubresourceIndex() const +{ + return mSubresourceIndex; +} + +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, + Renderer11 *renderer, + bool depth) + : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)), + mSwapChain(swapChain), + mDepth(depth) +{ + ASSERT(mSwapChain); +} + +SurfaceRenderTarget11::~SurfaceRenderTarget11() +{ +} + +GLsizei SurfaceRenderTarget11::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget11::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget11::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget11::getInternalFormat() const +{ + return GetSurfaceRTFormat(mDepth, mSwapChain); +} + +GLsizei SurfaceRenderTarget11::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +ID3D11Resource *SurfaceRenderTarget11::getTexture() const +{ + return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); +} + +ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const +{ + return (mDepth ? NULL : mSwapChain->getRenderTarget()); +} + +ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const +{ + return (mDepth ? mSwapChain->getDepthStencil() : NULL); +} + +ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const +{ + return (mDepth ? mSwapChain->getDepthStencilShaderResource() + : mSwapChain->getRenderTargetShaderResource()); +} + +ID3D11ShaderResourceView *SurfaceRenderTarget11::getBlitShaderResourceView() const +{ + // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits. + return getShaderResourceView(); +} + +unsigned int SurfaceRenderTarget11::getSubresourceIndex() const +{ + return 0; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h new file mode 100755 index 000000000..4ee0de292 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2012 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. +// + +// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/signal_utils.h" + +namespace rx +{ +class SwapChain11; +class Renderer11; + +class RenderTarget11 : public RenderTargetD3D +{ + public: + RenderTarget11(const d3d11::Format &formatSet); + virtual ~RenderTarget11(); + + virtual ID3D11Resource *getTexture() const = 0; + virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; + virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; + virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; + virtual ID3D11ShaderResourceView *getBlitShaderResourceView() const = 0; + + virtual unsigned int getSubresourceIndex() const = 0; + + void signalDirty() override; + angle::BroadcastChannel *getBroadcastChannel() { return &mBroadcastChannel; } + + const d3d11::Format &getFormatSet() const { return mFormatSet; } + + protected: + angle::BroadcastChannel mBroadcastChannel; + const d3d11::Format &mFormatSet; +}; + +class TextureRenderTarget11 : public RenderTarget11 +{ + public: + // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them + TextureRenderTarget11(ID3D11RenderTargetView *rtv, + ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, + ID3D11ShaderResourceView *blitSRV, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + TextureRenderTarget11(ID3D11DepthStencilView *dsv, + ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + virtual ~TextureRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + ID3D11ShaderResourceView *getBlitShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + private: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + GLsizei mSamples; + + unsigned int mSubresourceIndex; + ID3D11Resource *mTexture; + ID3D11RenderTargetView *mRenderTarget; + ID3D11DepthStencilView *mDepthStencil; + ID3D11ShaderResourceView *mShaderResource; + + // Shader resource view to use with internal blit shaders. Not set for depth/stencil render + // targets. + ID3D11ShaderResourceView *mBlitShaderResource; +}; + +class SurfaceRenderTarget11 : public RenderTarget11 +{ + public: + SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth); + virtual ~SurfaceRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + ID3D11ShaderResourceView *getBlitShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + private: + SwapChain11 *mSwapChain; + bool mDepth; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp new file mode 100755 index 000000000..8b4abaf9c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -0,0 +1,4614 @@ +// +// 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 <EGL/eglext.h> +#include <iomanip> +#include <sstream> +#include <versionhelpers.h> + +#include "common/tls.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/Program.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.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/Context11.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.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/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.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/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.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/VertexDataManager.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "third_party/trace_event/trace_event.h" + +#ifdef ANGLE_ENABLE_WINDOWS_STORE +#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h" +#else +#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" +#endif + +// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer +// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus +// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. +#ifdef ANGLE_ENABLE_D3D9 +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" +#endif + +// 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 +{ + +enum +{ + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 +}; + +enum ANGLEFeatureLevel +{ + ANGLE_FEATURE_LEVEL_INVALID, + ANGLE_FEATURE_LEVEL_9_3, + ANGLE_FEATURE_LEVEL_10_0, + ANGLE_FEATURE_LEVEL_10_1, + ANGLE_FEATURE_LEVEL_11_0, + ANGLE_FEATURE_LEVEL_11_1, + NUM_ANGLE_FEATURE_LEVELS +}; + +ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) +{ + switch (d3dFeatureLevel) + { + case D3D_FEATURE_LEVEL_9_3: + return ANGLE_FEATURE_LEVEL_9_3; + case D3D_FEATURE_LEVEL_10_0: + return ANGLE_FEATURE_LEVEL_10_0; + case D3D_FEATURE_LEVEL_10_1: + return ANGLE_FEATURE_LEVEL_10_1; + case D3D_FEATURE_LEVEL_11_0: + return ANGLE_FEATURE_LEVEL_11_0; + // Note: we don't ever request a 11_1 device, because this gives + // an E_INVALIDARG error on systems that don't have the platform update. + case D3D_FEATURE_LEVEL_11_1: + return ANGLE_FEATURE_LEVEL_11_1; + default: + return ANGLE_FEATURE_LEVEL_INVALID; + } +} + +void SetLineLoopIndices(GLuint *dest, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + dest[i] = static_cast<GLuint>(i); + } + dest[count] = 0; +} + +template <typename T> +void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count) +{ + const T *srcPtr = static_cast<const T *>(indices); + for (size_t i = 0; i < count; ++i) + { + dest[i] = static_cast<GLuint>(srcPtr[i]); + } + dest[count] = static_cast<GLuint>(srcPtr[0]); +} + +void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) +{ + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = 0; + destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1; + destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2; + } +} + +template <typename T> +void CopyLineLoopIndicesWithRestart(const GLvoid *indices, + size_t count, + GLenum indexType, + std::vector<GLuint> *bufferOut) +{ + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex()); + const T *srcPtr = static_cast<const T *>(indices); + Optional<GLuint> currentLoopStart; + + bufferOut->clear(); + + for (size_t indexIdx = 0; indexIdx < count; ++indexIdx) + { + GLuint value = static_cast<GLuint>(srcPtr[indexIdx]); + + if (value == restartIndex) + { + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + bufferOut->push_back(d3dRestartIndex); + currentLoopStart.reset(); + } + } + else + { + bufferOut->push_back(value); + if (!currentLoopStart.valid()) + { + currentLoopStart = value; + } + } + } + + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + } +} + +void GetLineLoopIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector<GLuint> *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + bufferOut->resize(static_cast<size_t>(count) + 1); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetLineLoopIndices(&(*bufferOut)[0], count); + break; + case GL_UNSIGNED_BYTE: + CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count); + break; + default: + UNREACHABLE(); + break; + } +} + +template <typename T> +void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris) +{ + const T *srcPtr = static_cast<const T *>(indices); + + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]); + destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]); + destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]); + } +} + +template <typename T> +void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, + GLuint indexCount, + GLenum indexType, + std::vector<GLuint> *bufferOut) +{ + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT); + const T *srcPtr = static_cast<const T *>(indices); + Optional<GLuint> vertexA; + Optional<GLuint> vertexB; + + bufferOut->clear(); + + for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx) + { + GLuint value = static_cast<GLuint>(srcPtr[indexIdx]); + + if (value == restartIndex) + { + bufferOut->push_back(d3dRestartIndex); + vertexA.reset(); + vertexB.reset(); + } + else + { + if (!vertexA.valid()) + { + vertexA = value; + } + else if (!vertexB.valid()) + { + vertexB = value; + } + else + { + bufferOut->push_back(vertexA.value()); + bufferOut->push_back(vertexB.value()); + bufferOut->push_back(value); + vertexB = value; + } + } + } +} + +void GetTriFanIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector<GLuint> *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + GLuint numTris = count - 2; + bufferOut->resize(numTris * 3); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetTriangleFanIndices(&(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris); + break; + default: + UNREACHABLE(); + break; + } +} + +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; + } +} + +// If we request a scratch buffer requesting a smaller size this many times, +// release and recreate the scratch buffer. This ensures we don't have a +// degenerate case where we are stuck hogging memory. +const int ScratchMemoryBufferLifetime = 1000; + +} // anonymous namespace + +Renderer11::Renderer11(egl::Display *display) + : RendererD3D(display), + mStateCache(this), + mStateManager(this), + mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()), + mDebug(nullptr), + mScratchMemoryBufferResetCounter(0), + mAnnotator(nullptr) +{ + mVertexDataManager = NULL; + mIndexDataManager = NULL; + + mLineLoopIB = NULL; + mTriangleFanIB = NULL; + mAppliedIBChanged = false; + + mBlit = NULL; + mPixelTransfer = NULL; + + mClear = NULL; + + mTrim = NULL; + + mSyncQuery = NULL; + + mRenderer11DeviceCaps.supportsClearView = false; + mRenderer11DeviceCaps.supportsConstantBufferOffsets = false; + mRenderer11DeviceCaps.supportsDXGI1_2 = false; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G5R5A1support = 0; + + mD3d11Module = NULL; + mDxgiModule = NULL; + mDCompModule = NULL; + mCreatedWithDeviceEXT = false; + mEGLDevice = nullptr; + + mDevice = NULL; + mDeviceContext = NULL; + mDeviceContext1 = NULL; + mDxgiAdapter = NULL; + mDxgiFactory = NULL; + + mDriverConstantBufferVS = NULL; + mDriverConstantBufferPS = NULL; + + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mAppliedPixelShader = NULL; + + mAppliedTFObject = angle::DirtyPointer; + + ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); + + if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + const auto &attributes = mDisplay->getAttributeMap(); + + EGLint requestedMajorVersion = static_cast<EGLint>( + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); + EGLint requestedMinorVersion = static_cast<EGLint>( + 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); + } + + EGLint requestedDeviceType = static_cast<EGLint>(attributes.get( + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE)); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_WARP; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_NULL; + break; + + default: + UNREACHABLE(); + } + + const EGLenum presentPath = static_cast<EGLenum>(attributes.get( + EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE)); + mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE); + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { + mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice()); + ASSERT(mEGLDevice != nullptr); + mCreatedWithDeviceEXT = true; + + // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE + // mAvailableFeatureLevels defaults to empty + mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; + mPresentPathFastEnabled = false; + } + +// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface +// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics +// Diagnostics tools in Visual Studio 2013. +// The D3D9 annotator works properly for both D3D11 and D3D9. +// Incorrect status reporting can cause ANGLE to log unnecessary debug events. +#ifdef ANGLE_ENABLE_D3D9 + mAnnotator = new DebugAnnotator9(); +#else + mAnnotator = new DebugAnnotator11(); +#endif + ASSERT(mAnnotator); + gl::InitializeDebugAnnotations(mAnnotator); +} + +Renderer11::~Renderer11() +{ + release(); +} + +#ifndef __d3d11_1_h__ +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) +#endif + +egl::Error Renderer11::initialize() +{ + HRESULT result = S_OK; + + ANGLE_TRY(initializeD3DDevice()); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#if !ANGLE_SKIP_DXGI_1_2_CHECK + { + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)"); + // 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(mDisplay->getNativeDisplayId()); + 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)) + { + return egl::Error( + EGL_NOT_INITIALIZED, D3D11_INIT_INCOMPATIBLE_DXGI, + "DXGI 1.2 required to present to HWNDs owned by another process."); + } + SafeRelease(dxgiDevice2); + } + } +#endif +#endif + + { + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); + // 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)) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR, + "Could not query DXGI device."); + } + + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter); + + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR, + "Could not retrieve DXGI adapter"); + } + + 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 (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL) + { + DXGI_ADAPTER_DESC2 adapterDesc2 = {}; + result = dxgiAdapter2->GetDesc2(&adapterDesc2); + if (SUCCEEDED(result)) + { + // 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 + { + result = mDxgiAdapter->GetDesc(&mAdapterDescription); + } + + SafeRelease(dxgiAdapter2); + + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR, + "Could not read DXGI adaptor description."); + } + + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory); + + if (!mDxgiFactory || FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR, + "Could not create DXGI factory."); + } + } + +// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + { + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)"); + 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 = {}; + filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages)); + filter.DenyList.pIDList = hideMessages; + + infoQueue->AddStorageFilterEntries(&filter); + SafeRelease(infoQueue); + } + } +#endif + +#if !defined(NDEBUG) + mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice); +#endif + + initializeDevice(); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error Renderer11::initializeD3DDevice() +{ + HRESULT result = S_OK; + + if (!mCreatedWithDeviceEXT) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS"); + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + mDCompModule = LoadLibrary(TEXT("dcomp.dll")); + + if (mD3d11Module == nullptr || mDxgiModule == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not load D3D11 or DXGI library."); + } + + // create the D3D11 device + ASSERT(mDevice == nullptr); + D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>( + GetProcAddress(mD3d11Module, "D3D11CreateDevice")); + + if (D3D11CreateDevice == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not retrieve D3D11CreateDevice address."); + } + } +#endif + +#ifdef _DEBUG + { + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)"); + result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr, + D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(), + static_cast<unsigned int>(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &mDevice, + &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + } + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS"); + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice"); + + result = D3D11CreateDevice( + nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(), + static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, + &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + + // Cleanup done by destructor + if (!mDevice || FAILED(result)) + { + ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", + static_cast<int>(result)); + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR, + "Could not create D3D11 device."); + } + } + } + else + { + // We should use the inputted D3D11 device instead + void *device = nullptr; + ANGLE_TRY(mEGLDevice->getDevice(&device)); + + ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device); + if (FAILED(d3dDevice->GetDeviceRemovedReason())) + { + return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost."); + } + + if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Inputted D3D11 device must be Feature Level 9_3 or greater."); + } + + // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. + mDevice = d3dDevice; + mDevice->AddRef(); + mDevice->GetImmediateContext(&mDeviceContext); + mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); + } + + d3d11::SetDebugName(mDeviceContext, "DeviceContext"); + + return egl::Error(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() +{ + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS"); + TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice"); + + populateRenderer11DeviceCaps(); + + mStateCache.initialize(mDevice); + mInputLayoutCache.initialize(mDevice, mDeviceContext); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this, getRendererClass()); + + ASSERT(!mBlit); + mBlit = new Blit11(this); + + ASSERT(!mClear); + mClear = new Clear11(this); + + const auto &attributes = mDisplay->getAttributeMap(); + // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application + // automatically when an application is suspended by the OS. This feature is currently + // only supported for Windows Store applications. + EGLint enableAutoTrim = static_cast<EGLint>( + attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE)); + + if (enableAutoTrim == EGL_TRUE) + { + ASSERT(!mTrim); + mTrim = new Trim11(this); + } + + ASSERT(!mPixelTransfer); + mPixelTransfer = new PixelTransfer11(this); + + const gl::Caps &rendererCaps = getNativeCaps(); + + mStateManager.initialize(rendererCaps); + + mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mSamplerMetadataVS.initData(rendererCaps.maxVertexTextureImageUnits); + + mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + mSamplerMetadataPS.initData(rendererCaps.maxTextureImageUnits); + + mStateManager.initialize(rendererCaps); + + markAllStateDirty(); + + // Gather stats on DXGI and D3D feature level + ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); + + ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel); + + // We don't actually request a 11_1 device, because of complications with the platform + // update. Instead we check if the mDeviceContext1 pointer cast succeeded. + // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0 + // because the app can specify a lower version (such as 9_3) on Display creation. + if (mDeviceContext1 != nullptr) + { + angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1; + } + + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel, + NUM_ANGLE_FEATURE_LEVELS); +} + +void Renderer11::populateRenderer11DeviceCaps() +{ + HRESULT hr = S_OK; + + LARGE_INTEGER version; + hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.driverVersion.reset(); + ERR("Error querying driver version from DXGI Adapter."); + } + else + { + mRenderer11DeviceCaps.driverVersion = version; + } + + if (mDeviceContext1) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, + sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + if (SUCCEEDED(result)) + { + mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE); + mRenderer11DeviceCaps.supportsConstantBufferOffsets = + (d3d11Options.ConstantBufferOffsetting != FALSE); + } + } + + if (getWorkarounds().disableB5G6R5Support) + { + mRenderer11DeviceCaps.B5G6R5support = 0; + } + else + { + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, + &(mRenderer11DeviceCaps.B5G6R5support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B5G6R5support = 0; + } + } + + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM, + &(mRenderer11DeviceCaps.B4G4R4A4support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B4G4R4A4support = 0; + } + + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM, + &(mRenderer11DeviceCaps.B5G5R5A1support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B5G5R5A1support = 0; + } + + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter); + mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); + SafeRelease(dxgiAdapter2); +} + +egl::ConfigSet Renderer11::generateConfigs() +{ + std::vector<GLenum> colorBufferFormats; + + // 32-bit supported formats + colorBufferFormats.push_back(GL_BGRA8_EXT); + colorBufferFormats.push_back(GL_RGBA8_OES); + + // 24-bit supported formats + colorBufferFormats.push_back(GL_RGB8_OES); + + if (!mPresentPathFastEnabled) + { + // 16-bit supported formats + // These aren't valid D3D11 swapchain formats, so don't expose them as configs + // if present path fast is active + colorBufferFormats.push_back(GL_RGBA4); + colorBufferFormats.push_back(GL_RGB5_A1); + colorBufferFormats.push_back(GL_RGB565); + } + + static const GLenum depthStencilBufferFormats[] = { + GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getNativeCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); + + const EGLint optimalSurfaceOrientation = + mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; + + egl::ConfigSet configs; + for (GLenum colorBufferInternalFormat : colorBufferFormats) + { + const gl::TextureCaps &colorBufferFormatCaps = + rendererTextureCaps.get(colorBufferInternalFormat); + if (!colorBufferFormatCaps.renderable) + { + continue; + } + + for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats) + { + const gl::TextureCaps &depthStencilBufferFormatCaps = + rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (!depthStencilBufferFormatCaps.renderable && + depthStencilBufferInternalFormat != GL_NONE) + { + continue; + } + + const gl::InternalFormat &colorBufferFormatInfo = + gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = + gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + const gl::Version &maxVersion = getMaxSupportedESVersion(); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || + colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + config.configCaveat = EGL_NONE; + config.configID = static_cast<EGLint>(configs.size() + 1); + + // PresentPathFast may not be conformant + config.conformant = 0; + if (!mPresentPathFastEnabled) + { + // Can only support a conformant ES2 with feature level greater than 10.0. + if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + { + config.conformant |= EGL_OPENGL_ES2_BIT; + } + + // We can only support conformant ES3 on FL 10.1+ + if (maxVersion.major >= 3) + { + config.conformant |= EGL_OPENGL_ES3_BIT_KHR; + } + } + + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = 4; + config.minSwapInterval = 0; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + + // Can't support ES3 at all without feature level 10.1 + config.renderableType = EGL_OPENGL_ES2_BIT; + if (maxVersion.major >= 3) + { + config.renderableType |= EGL_OPENGL_ES3_BIT_KHR; + } + + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + config.optimalOrientation = optimalSurfaceOrientation; + + configs.add(config); + } + } + + ASSERT(configs.size() > 0); + return configs; +} + +void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + if (getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + outExtensions->d3dTextureClientBuffer = true; + + outExtensions->keyedMutex = true; + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + + // If present path fast is active then the surface orientation extension isn't supported + outExtensions->surfaceOrientation = !mPresentPathFastEnabled; + + // D3D11 does not support present with dirty rectangles until DXGI 1.2. + outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; + + outExtensions->deviceQuery = true; + + outExtensions->image = true; + outExtensions->imageBase = true; + outExtensions->glTexture2DImage = true; + outExtensions->glTextureCubemapImage = true; + outExtensions->glRenderbufferImage = true; + + outExtensions->stream = true; + outExtensions->streamConsumerGLTexture = true; + outExtensions->streamConsumerGLTextureYUV = true; + // Not all D3D11 devices support NV12 textures + if (getNV12TextureSupport()) + { + outExtensions->streamProducerD3DTextureNV12 = true; + } + + outExtensions->flexibleSurfaceCompatibility = true; + outExtensions->directComposition = !!mDCompModule; +} + +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); + + unsigned int attempt = 0; + do + { + unsigned int flushFrequency = 100; + UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH; + attempt++; + + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, flags); + 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); +} + +bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const +{ +#ifdef ANGLE_ENABLE_WINDOWS_STORE + return NativeWindow11WinRT::IsValidNativeWindow(window); +#else + return NativeWindow11Win32::IsValidNativeWindow(window); +#endif +} + +NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const +{ +#ifdef ANGLE_ENABLE_WINDOWS_STORE + UNUSED_VARIABLE(attribs); + return new NativeWindow11WinRT(window, config->alphaSize > 0); +#else + return new NativeWindow11Win32( + window, config->alphaSize > 0, + attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE); +#endif +} + +egl::Error Renderer11::getD3DTextureInfo(IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const +{ + ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture); + if (texture == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a ID3D11Texture2D"); + } + + ID3D11Device *textureDevice = nullptr; + texture->GetDevice(&textureDevice); + if (textureDevice != mDevice) + { + SafeRelease(texture); + return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match."); + } + SafeRelease(textureDevice); + + D3D11_TEXTURE2D_DESC desc = {0}; + texture->GetDesc(&desc); + SafeRelease(texture); + + if (width) + { + *width = static_cast<EGLint>(desc.Width); + } + if (height) + { + *height = static_cast<EGLint>(desc.Height); + } + + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (desc.Format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + break; + + default: + return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", + desc.Format); + } + + if (fboFormat) + { + const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format); + *fboFormat = angleFormat.fboImplementationInternalFormat; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error Renderer11::validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const +{ + if (shareHandle == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, "NULL share handle."); + } + + ID3D11Resource *tempResource11 = nullptr; + HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result); + } + + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11); + SafeRelease(tempResource11); + + if (texture2D == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, + "Failed to query ID3D11Texture2D object from share handle."); + } + + D3D11_TEXTURE2D_DESC desc = {0}; + texture2D->GetDesc(&desc); + SafeRelease(texture2D); + + EGLint width = attribs.getAsInt(EGL_WIDTH, 0); + EGLint height = attribs.getAsInt(EGL_HEIGHT, 0); + ASSERT(width != 0 && height != 0); + + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps()); + + if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) || + desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1) + { + return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture."); + } + + return egl::Error(EGL_SUCCESS); +} + +SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) +{ + return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture, + backBufferFormat, depthBufferFormat, orientation); +} + +void *Renderer11::getD3DDevice() +{ + return reinterpret_cast<void *>(mDevice); +} + +gl::Error Renderer11::generateSwizzle(gl::Texture *texture) +{ + if (texture) + { + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + ASSERT(textureD3D); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(&texStorage)); + + if (texStorage) + { + TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); + const gl::TextureState &textureState = texture->getTextureState(); + ANGLE_TRY(storage11->generateSwizzles(textureState.getSwizzleState())); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::generateSwizzles(const gl::ContextState &data, gl::SamplerType type) +{ + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().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, data.getCaps()); + if (textureUnit != -1) + { + gl::Texture *texture = data.getState().getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getTextureState().swizzleRequired()) + { + ANGLE_TRY(generateSwizzle(texture)); + } + } + } + + return gl::NoError(); +} + +gl::Error Renderer11::generateSwizzles(const gl::ContextState &data) +{ + ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_VERTEX)); + ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} +gl::Error Renderer11::setSamplerState(gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &samplerState) +{ + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + + TextureStorage *storage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(&storage)); + + // Storage should exist, texture should be complete + ASSERT(storage); + + // 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. + SamplerMetadataD3D11 *metadata = nullptr; + + if (type == gl::SAMPLER_PIXEL) + { + ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits); + + if (mForceSetPixelSamplerStates[index] || + memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = NULL; + ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != NULL); + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + + metadata = &mSamplerMetadataPS; + } + else if (type == gl::SAMPLER_VERTEX) + { + ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits); + + if (mForceSetVertexSamplerStates[index] || + memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = NULL; + ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != NULL); + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + + metadata = &mSamplerMetadataVS; + } + else + UNREACHABLE(); + + ASSERT(metadata != nullptr); + metadata->update(index, *texture); + + return gl::NoError(); +} + +gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + ID3D11ShaderResourceView *textureSRV = NULL; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureImpl->getNativeTexture(&texStorage)); + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); + + ANGLE_TRY(storage11->getSRV(texture->getTextureState(), &textureSRV)); + + // 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) < getNativeCaps().maxTextureImageUnits) || + (type == gl::SAMPLER_VERTEX && + static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits)); + + mStateManager.setShaderResource(type, index, textureSRV); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setUniformBuffers(const gl::ContextState &data, + const std::vector<GLint> &vertexUniformBuffers, + const std::vector<GLint> &fragmentUniformBuffers) +{ + for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size(); + uniformBufferIndex++) + { + GLint binding = vertexUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + const OffsetBindingPointer<gl::Buffer> &uniformBuffer = + data.getState().getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) + { + continue; + } + + Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); + ID3D11Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize, + &constantBuffer, &firstConstant, + &numConstants)); + + if (!constantBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer"); + } + + if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) + { + if (firstConstant != 0 && uniformBufferSize != 0) + { + ASSERT(numConstants != 0); + mDeviceContext1->VSSetConstantBuffers1( + getReservedVertexUniformBuffers() + + static_cast<unsigned int>(uniformBufferIndex), + 1, &constantBuffer, &firstConstant, &numConstants); + } + else + { + mDeviceContext->VSSetConstantBuffers( + getReservedVertexUniformBuffers() + + static_cast<unsigned int>(uniformBufferIndex), + 1, &constantBuffer); + } + + mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize; + } + } + + for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size(); + uniformBufferIndex++) + { + GLint binding = fragmentUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + const OffsetBindingPointer<gl::Buffer> &uniformBuffer = + data.getState().getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) + { + continue; + } + + Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); + ID3D11Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize, + &constantBuffer, &firstConstant, + &numConstants)); + + if (!constantBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer"); + } + + if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) + { + if (firstConstant != 0 && uniformBufferSize != 0) + { + mDeviceContext1->PSSetConstantBuffers1( + getReservedFragmentUniformBuffers() + + static_cast<unsigned int>(uniformBufferIndex), + 1, &constantBuffer, &firstConstant, &numConstants); + } + else + { + mDeviceContext->PSSetConstantBuffers( + getReservedFragmentUniformBuffers() + + static_cast<unsigned int>(uniformBufferIndex), + 1, &constantBuffer); + } + + mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize; + } + } + + return gl::NoError(); +} + +gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode) +{ + const auto &glState = data.getState(); + + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data)); + ANGLE_TRY(applyRenderTarget(framebuffer)); + + // Set the present path state + auto firstColorAttachment = framebuffer->getFirstColorbuffer(); + const bool presentPathFastActive = UsePresentPathFast(this, firstColorAttachment); + mStateManager.updatePresentPath(presentPathFastActive, firstColorAttachment); + + // Setting viewport state + mStateManager.setViewport(&data.getCaps(), glState.getViewport(), glState.getNearPlane(), + glState.getFarPlane()); + + // Setting scissor state + mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); + + // Applying rasterizer state to D3D11 device + // Since framebuffer->getSamples will return the original samples which may be different with + // the sample counts that we set in render target view, here we use renderTarget->getSamples to + // get the actual samples. + GLsizei samples = 0; + if (firstColorAttachment) + { + ASSERT(firstColorAttachment->isAttached()); + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget)); + samples = renderTarget->getSamples(); + } + gl::RasterizerState rasterizer = glState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + ANGLE_TRY(mStateManager.setRasterizerState(rasterizer)); + + // Setting blend state + unsigned int mask = GetBlendSampleMask(data, samples); + ANGLE_TRY(mStateManager.setBlendState(framebuffer, glState.getBlendState(), + glState.getBlendColor(), mask)); + + // Setting depth stencil state + ANGLE_TRY(mStateManager.setDepthStencilState(glState)); + + return gl::NoError(); +} + +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; +} + +gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + return mStateManager.syncFramebuffer(framebuffer); +} + +gl::Error Renderer11::applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo) +{ + const auto &vertexArray = state.getVertexArray(); + auto *vertexArray11 = GetImplAs<VertexArray11>(vertexArray); + + ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first, count, + instances)); + + ANGLE_TRY(mStateManager.updateCurrentValueAttribs(state, mVertexDataManager)); + + // If index information is passed, mark it with the current changed status. + if (indexInfo) + { + indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged; + } + + GLsizei numIndicesPerInstance = 0; + if (instances > 0) + { + numIndicesPerInstance = count; + } + const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs(); + const auto ¤tValueAttribs = mStateManager.getCurrentValueAttribs(); + ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs, + mode, first, indexInfo, numIndicesPerInstance)); + + // 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(state, count); + + return gl::NoError(); +} + +gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) +{ + const auto &glState = data.getState(); + gl::VertexArray *vao = glState.getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + ANGLE_TRY(mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, + indexInfo, glState.isPrimitiveRestartEnabled())); + + 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(BUFFER_USAGE_INDEX), buffer); + } + else + { + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer); + buffer = indexBuffer->getBuffer(); + } + + mAppliedIBChanged = false; + if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || + indexInfo->startOffset != mAppliedIBOffset) + { + mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); + + mAppliedIB = buffer; + mAppliedIBFormat = bufferFormat; + mAppliedIBOffset = indexInfo->startOffset; + mAppliedIBChanged = true; + } + + return gl::NoError(); +} + +gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::ContextState &data) +{ + const auto &state = data.getState(); + + // If transform feedback is not active, unbind all buffers + if (!state.isTransformFeedbackActiveUnpaused()) + { + if (mAppliedTFObject != 0) + { + mDeviceContext->SOSetTargets(0, nullptr, nullptr); + mAppliedTFObject = 0; + } + return gl::NoError(); + } + + gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); + TransformFeedback11 *transformFeedback11 = GetImplAs<TransformFeedback11>(transformFeedback); + uintptr_t transformFeedbackId = reinterpret_cast<uintptr_t>(transformFeedback11); + if (mAppliedTFObject == transformFeedbackId && !transformFeedback11->isDirty()) + { + return gl::NoError(); + } + + const std::vector<ID3D11Buffer *> *soBuffers = nullptr; + ANGLE_TRY_RESULT(transformFeedback11->getSOBuffers(), soBuffers); + const std::vector<UINT> &soOffsets = transformFeedback11->getSOBufferOffsets(); + + mDeviceContext->SOSetTargets(transformFeedback11->getNumSOBuffers(), soBuffers->data(), + soOffsets.data()); + + mAppliedTFObject = transformFeedbackId; + transformFeedback11->onApply(); + + return gl::NoError(); +} + +gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances) +{ + const auto &glState = data.getState(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused()) + { + // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback + // won't get the correct output. To work around this, draw with *only* the stream out + // first (no pixel shader) to feed the stream out buffers and then draw again with the + // geometry shader + pixel shader to rasterize the primitives. + mDeviceContext->PSSetShader(nullptr, nullptr, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + rx::ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY( + programD3D->getPixelExecutableForFramebuffer(glState.getDrawFramebuffer(), &pixelExe)); + + // Skip the draw call if rasterizer discard is enabled (or no fragment shader). + if (!pixelExe || glState.getRasterizerState().rasterizerDiscard) + { + return gl::Error(GL_NO_ERROR); + } + + ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader(); + ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + + // Retrieve the geometry shader. + rx::ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY( + programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr)); + + ID3D11GeometryShader *geometryShader = + (geometryExe ? GetAs<ShaderExecutable11>(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); + } + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances); + } + + if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); + } + + bool useInstancedPointSpriteEmulation = + programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation; + + if (instances > 0) + { + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a + // less efficent code path. + // Instanced rendering of emulated pointsprites requires a loop to draw each batch of + // points. An offset into the instanced data buffer is calculated and applied on each + // iteration to ensure all instances are rendered correctly. + + // Each instance being rendered requires the inputlayout cache to reapply buffers and + // offsets. + for (GLsizei i = 0; i < instances; i++) + { + ANGLE_TRY( + mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i)); + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + } + else + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + return gl::Error(GL_NO_ERROR); + } + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances) +{ + int minIndex = static_cast<int>(indexInfo.indexRange.start); + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(data, count, type, indices, &indexInfo, instances); + } + + if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(data, count, type, indices, minIndex, instances); + } + + const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram()); + if (instances > 0) + { + if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + { + // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a + // less efficent code path. + // Instanced rendering of emulated pointsprites requires a loop to draw each batch of + // points. An offset into the instanced data buffer is calculated and applied on each + // iteration to ensure all instances are rendered correctly. + GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount()); + + // Each instance being rendered requires the inputlayout cache to reapply buffers and + // offsets. + for (GLsizei i = 0; i < instances; i++) + { + ANGLE_TRY( + mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(minIndex, i)); + mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0); + } + } + else + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + } + return gl::Error(GL_NO_ERROR); + } + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + { + // The count parameter passed to drawElements represents the total number of instances + // to be rendered. Each instance is referenced by the bound index buffer from the + // the caller. + // + // Indexed pointsprite emulation replicates data for duplicate entries found + // in the index buffer. + // This is not an efficent rendering mechanism and is only used on downlevel renderers + // that do not support geometry shaders. + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + else + { + mDeviceContext->DrawIndexed(count, 0, -minIndex); + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::drawLineLoop(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indexPointer, + const TranslatedIndexData *indexInfo, + int instances) +{ + const auto &glState = data.getState(); + gl::VertexArray *vao = glState.getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indices = indexPointer; + + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + + const uint8_t *bufferData = NULL; + ANGLE_TRY(storage->getData(&bufferData)); + + indices = bufferData + offset; + } + + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = + mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast<unsigned int>(count) + 1 > + (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too " + "many indices required."); + } + + GetLineLoopIndices(indices, type, static_cast<GLuint>(count), + glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); + + unsigned int spaceNeeded = + static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size()); + ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); + + void *mappedMemory = NULL; + unsigned int offset; + ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); + + // Copy over the converted index data. + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], + sizeof(GLuint) * mScratchIndexDataBuffer.size()); + + ANGLE_TRY(mLineLoopIB->unmapBuffer()); + + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) + { + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = offset; + } + + INT baseVertexLocation = (indexInfo ? -static_cast<int>(indexInfo->indexRange.start) : 0); + UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0); + } + else + { + mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation); + } + + return gl::NoError(); +} + +gl::Error Renderer11::drawTriangleFan(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances) +{ + gl::VertexArray *vao = data.getState().getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indexPointer = indices; + + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + + const uint8_t *bufferData = NULL; + ANGLE_TRY(storage->getData(&bufferData)); + + indexPointer = bufferData + offset; + } + + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); + gl::Error error = + mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mTriangleFanIB); + return error; + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const GLuint numTris = count - 2; + + if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many " + "indices required."); + } + + GetTriFanIndices(indexPointer, type, count, data.getState().isPrimitiveRestartEnabled(), + &mScratchIndexDataBuffer); + + const unsigned int spaceNeeded = + static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); + ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); + + void *mappedMemory = nullptr; + unsigned int offset; + ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); + + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); + + ANGLE_TRY(mTriangleFanIB->unmapBuffer()); + + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) + { + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = offset; + } + + UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0); + } + else + { + mDeviceContext->DrawIndexed(indexCount, 0, -minIndex); + } + + return gl::NoError(); +} + +gl::Error Renderer11::applyShaders(const gl::ContextState &data, GLenum drawMode) +{ + const auto &glState = data.getState(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + programD3D->updateCachedInputLayout(glState); + + const auto &inputLayout = programD3D->getCachedInputLayout(); + + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr)); + + const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe)); + + ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY( + programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr)); + + ID3D11VertexShader *vertexShader = + (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr); + + ID3D11PixelShader *pixelShader = nullptr; + // Skip pixel shader if we're doing rasterizer discard. + bool rasterizerDiscard = glState.getRasterizerState().rasterizerDiscard; + if (!rasterizerDiscard) + { + pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr); + } + + ID3D11GeometryShader *geometryShader = nullptr; + bool transformFeedbackActive = glState.isTransformFeedbackActiveUnpaused(); + if (transformFeedbackActive) + { + geometryShader = + (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr); + } + else + { + geometryShader = + (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr); + } + + bool dirtyUniforms = false; + + if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader) + { + mDeviceContext->VSSetShader(vertexShader, nullptr, 0); + mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader); + dirtyUniforms = true; + } + + if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader) + { + mDeviceContext->GSSetShader(geometryShader, nullptr, 0); + mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); + dirtyUniforms = true; + } + + if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader) + { + mDeviceContext->PSSetShader(pixelShader, nullptr, 0); + mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader); + dirtyUniforms = true; + } + + if (dirtyUniforms) + { + programD3D->dirtyAllUniforms(); + } + + return programD3D->applyUniforms(drawMode); +} + +gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector<D3DUniform *> &uniformArray) +{ + unsigned int totalRegisterCountVS = 0; + unsigned int totalRegisterCountPS = 0; + + bool vertexUniformsDirty = false; + bool pixelUniformsDirty = false; + + for (const D3DUniform *uniform : uniformArray) + { + if (uniform->isReferencedByVertexShader() && !uniform->isSampler()) + { + totalRegisterCountVS += uniform->registerCount; + vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty); + } + + if (uniform->isReferencedByFragmentShader() && !uniform->isSampler()) + { + totalRegisterCountPS += uniform->registerCount; + pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty); + } + } + + const UniformStorage11 *vertexUniformStorage = + GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = + GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); + ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); + + float(*mapVS)[4] = NULL; + float(*mapPS)[4] = NULL; + + if (totalRegisterCountVS > 0 && vertexUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = + mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapVS = (float(*)[4])map.pData; + } + + if (totalRegisterCountPS > 0 && pixelUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = + mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } + + for (const D3DUniform *uniform : uniformArray) + { + if (uniform->isSampler()) + continue; + + unsigned int componentCount = (4 - uniform->registerElement); + + // we assume that uniforms from structs are arranged in struct order in our uniforms list. + // otherwise we would overwrite previously written regions of memory. + + if (uniform->isReferencedByVertexShader() && mapVS) + { + memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, + uniform->registerCount * sizeof(float) * componentCount); + } + + if (uniform->isReferencedByFragmentShader() && mapPS) + { + memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, + uniform->registerCount * sizeof(float) * componentCount); + } + } + + if (mapVS) + { + mDeviceContext->Unmap(vertexConstantBuffer, 0); + } + + if (mapPS) + { + mDeviceContext->Unmap(pixelConstantBuffer, 0); + } + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers( + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers( + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } + + if (!mDriverConstantBufferVS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc( + &constantBufferDescription, + sizeof(dx_VertexConstants11) + mSamplerMetadataVS.sizeBytes()); + HRESULT result = + mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferVS); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create vertex shader constant buffer, result: 0x%X.", + result); + } + mDeviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &mDriverConstantBufferVS); + } + if (!mDriverConstantBufferPS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, + sizeof(dx_PixelConstants11) + mSamplerMetadataPS.sizeBytes()); + HRESULT result = + mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferPS); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create pixel shader constant buffer, result: 0x%X.", + result); + } + mDeviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &mDriverConstantBufferPS); + } + + // 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. + const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants(); + size_t samplerMetadataReferencedBytesVS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * + programD3D.getUsedSamplerRange(gl::SAMPLER_VERTEX); + applyDriverConstantsIfNeeded(&mAppliedVertexConstants, vertexConstants, &mSamplerMetadataVS, + samplerMetadataReferencedBytesVS, mDriverConstantBufferVS); + + const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants(); + size_t samplerMetadataReferencedBytesPS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * + programD3D.getUsedSamplerRange(gl::SAMPLER_PIXEL); + applyDriverConstantsIfNeeded(&mAppliedPixelConstants, pixelConstants, &mSamplerMetadataPS, + samplerMetadataReferencedBytesPS, mDriverConstantBufferPS); + + // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary + if (programD3D.usesGeometryShader(drawMode)) + { + // needed for the point sprite geometry shader + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + ASSERT(mDriverConstantBufferPS != nullptr); + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } + } + + return gl::Error(GL_NO_ERROR); +} + +// SamplerMetadataD3D11 implementation + +Renderer11::SamplerMetadataD3D11::SamplerMetadataD3D11() : mDirty(true) +{ +} + +Renderer11::SamplerMetadataD3D11::~SamplerMetadataD3D11() +{ +} + +void Renderer11::SamplerMetadataD3D11::initData(unsigned int samplerCount) +{ + mSamplerMetadata.resize(samplerCount); +} + +void Renderer11::SamplerMetadataD3D11::update(unsigned int samplerIndex, const gl::Texture &texture) +{ + unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel(); + GLenum sizedFormat = texture.getFormat(texture.getTarget(), baseLevel).asSized(); + if (mSamplerMetadata[samplerIndex].baseLevel != static_cast<int>(baseLevel)) + { + mSamplerMetadata[samplerIndex].baseLevel = static_cast<int>(baseLevel); + mDirty = 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 (mSamplerMetadata[samplerIndex].internalFormatBits != internalFormatBits) + { + mSamplerMetadata[samplerIndex].internalFormatBits = internalFormatBits; + mDirty = 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 (mSamplerMetadata[samplerIndex].wrapModes != wrapModes) + { + mSamplerMetadata[samplerIndex].wrapModes = wrapModes; + mDirty = true; + } + } +} + +const Renderer11::SamplerMetadataD3D11::dx_SamplerMetadata * +Renderer11::SamplerMetadataD3D11::getData() const +{ + return mSamplerMetadata.data(); +} + +size_t Renderer11::SamplerMetadataD3D11::sizeBytes() const +{ + return sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * mSamplerMetadata.size(); +} + +template <class TShaderConstants> +void Renderer11::applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants, + const TShaderConstants &constants, + SamplerMetadataD3D11 *samplerMetadata, + size_t samplerMetadataReferencedBytes, + ID3D11Buffer *driverConstantBuffer) +{ + ASSERT(driverConstantBuffer != nullptr); + if (memcmp(appliedConstants, &constants, sizeof(TShaderConstants)) != 0 || + samplerMetadata->isDirty()) + { + memcpy(appliedConstants, &constants, sizeof(TShaderConstants)); + + D3D11_MAPPED_SUBRESOURCE mapping = {0}; + HRESULT result = + mDeviceContext->Map(driverConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping); + ASSERT(SUCCEEDED(result)); + memcpy(mapping.pData, appliedConstants, sizeof(TShaderConstants)); + // Previous buffer contents were discarded, so we need to refresh also the area of the + // buffer that isn't used by this program. + memcpy(&reinterpret_cast<uint8_t *>(mapping.pData)[sizeof(TShaderConstants)], + samplerMetadata->getData(), samplerMetadata->sizeBytes()); + mDeviceContext->Unmap(driverConstantBuffer, 0); + + samplerMetadata->markClean(); + } +} + +template void Renderer11::applyDriverConstantsIfNeeded<dx_VertexConstants11>( + dx_VertexConstants11 *appliedConstants, + const dx_VertexConstants11 &constants, + SamplerMetadataD3D11 *samplerMetadata, + size_t samplerMetadataReferencedBytes, + ID3D11Buffer *driverConstantBuffer); +template void Renderer11::applyDriverConstantsIfNeeded<dx_PixelConstants11>( + dx_PixelConstants11 *appliedConstants, + const dx_PixelConstants11 &constants, + SamplerMetadataD3D11 *samplerMetadata, + size_t samplerMetadataReferencedBytes, + ID3D11Buffer *driverConstantBuffer); + +void Renderer11::markAllStateDirty() +{ + TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty"); + + for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) + { + mForceSetVertexSamplerStates[vsamplerId] = true; + } + + for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) + { + mForceSetPixelSamplerStates[fsamplerId] = true; + } + + mStateManager.invalidateEverything(); + + mAppliedIB = NULL; + mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; + mAppliedIBOffset = 0; + + mAppliedVertexShader = angle::DirtyPointer; + mAppliedGeometryShader = angle::DirtyPointer; + mAppliedPixelShader = angle::DirtyPointer; + + mAppliedTFObject = angle::DirtyPointer; + + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11)); + + mInputLayoutCache.markDirty(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) + { + mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1); + mCurrentConstantBufferVSOffset[i] = 0; + mCurrentConstantBufferVSSize[i] = 0; + mCurrentConstantBufferPS[i] = static_cast<unsigned int>(-1); + mCurrentConstantBufferPSOffset[i] = 0; + mCurrentConstantBufferPSSize[i] = 0; + } + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +void Renderer11::releaseDeviceResources() +{ + mStateManager.deinitialize(); + mStateCache.clear(); + mInputLayoutCache.clear(); + + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mTriangleFanIB); + SafeDelete(mBlit); + SafeDelete(mClear); + SafeDelete(mTrim); + SafeDelete(mPixelTransfer); + + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer11::testDeviceLost() +{ + bool isLost = false; + + if (!mDevice) + { + return true; + } + + // GetRemovedReason is used to test if the device is removed + HRESULT result = mDevice->GetDeviceRemovedReason(); + isLost = d3d11::isDeviceLostError(result); + + if (isLost) + { + ERR("The D3D11 device was removed: 0x%08X", result); + } + + return isLost; +} + +bool Renderer11::testDeviceResettable() +{ + // determine if the device is resettable by creating a dummy device + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = + (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + return false; + } + + ID3D11Device *dummyDevice; + D3D_FEATURE_LEVEL dummyFeatureLevel; + ID3D11DeviceContext *dummyContext; + + ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN); + HRESULT result = D3D11CreateDevice( + NULL, mRequestedDriverType, NULL, +#if defined(_DEBUG) + D3D11_CREATE_DEVICE_DEBUG, +#else + 0, +#endif + mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext); + + if (!mDevice || FAILED(result)) + { + return false; + } + + SafeRelease(dummyContext); + SafeRelease(dummyDevice); + + return true; +} + +void Renderer11::release() +{ + RendererD3D::cleanup(); + + mScratchMemoryBuffer.resize(0); + + if (mAnnotator != nullptr) + { + gl::UninitializeDebugAnnotations(); + SafeDelete(mAnnotator); + } + + releaseDeviceResources(); + + if (!mCreatedWithDeviceEXT) + { + // Only delete the device if the Renderer11 owns it + // Otherwise we should keep it around in case we try to reinitialize the renderer later + SafeDelete(mEGLDevice); + } + + SafeRelease(mDxgiFactory); + SafeRelease(mDxgiAdapter); + + SafeRelease(mDeviceContext1); + + if (mDeviceContext) + { + mDeviceContext->ClearState(); + mDeviceContext->Flush(); + SafeRelease(mDeviceContext); + } + + SafeRelease(mDevice); + SafeRelease(mDebug); + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = NULL; + } + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = NULL; + } + + if (mDCompModule) + { + FreeLibrary(mDCompModule); + mDCompModule = NULL; + } + + mCompiler.release(); + + mSupportsShareHandles.reset(); +} + +bool Renderer11::resetDevice() +{ + // recreate everything + release(); + egl::Error result = initialize(); + + if (result.isError()) + { + ERR("Could not reinitialize D3D11 device: %08X", result.getCode()); + return false; + } + + return true; +} + +SIZE_T Renderer11::getMaxResourceSize() const +{ + // This formula comes from http://msdn.microsoft.com/en-us/library/windows/desktop/ff819065%28v=vs.85%29.aspx + return std::min(std::max(SIZE_T(128 * 1024 * 1024), mAdapterDescription.DedicatedVideoMemory), SIZE_T(2048) * 1024 * 1024); +} + +std::string Renderer11::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mDescription; + rendererString << " Direct3D11"; + + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + + return rendererString.str(); +} + +DeviceIdentifier Renderer11::getAdapterIdentifier() const +{ + // Don't use the AdapterLuid here, since that doesn't persist across reboot. + DeviceIdentifier deviceIdentifier = {0}; + deviceIdentifier.VendorId = mAdapterDescription.VendorId; + deviceIdentifier.DeviceId = mAdapterDescription.DeviceId; + deviceIdentifier.SubSysId = mAdapterDescription.SubSysId; + deviceIdentifier.Revision = mAdapterDescription.Revision; + deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel); + + return deviceIdentifier; +} + +unsigned int Renderer11::getReservedVertexUniformVectors() const +{ + // Driver uniforms are stored in a separate constant buffer + return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel); +} + +unsigned int Renderer11::getReservedFragmentUniformVectors() const +{ + // Driver uniforms are stored in a separate constant buffer + return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel); +} + +unsigned int Renderer11::getReservedVertexUniformBuffers() const +{ + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +unsigned int Renderer11::getReservedFragmentUniformBuffers() const +{ + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const +{ + if (mCreatedWithDeviceEXT) + { + return d3d11::GetDeviceType(mDevice); + } + + if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) || + (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) || + (mRequestedDriverType == D3D_DRIVER_TYPE_NULL)) + { + return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL; + } + + if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) + { + return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP; + } + + return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE; +} + +bool Renderer11::getShareHandleSupport() const +{ + if (mSupportsShareHandles.valid()) + { + return mSupportsShareHandles.value(); + } + + // We only currently support share handles with BGRA surfaces, because + // chrome needs BGRA. Once chrome fixes this, we should always support them. + if (!getNativeExtensions().textureFormatBGRA8888) + { + mSupportsShareHandles = false; + return false; + } + + // PIX doesn't seem to support using share handles, so disable them. + if (gl::DebugAnnotationsActive()) + { + mSupportsShareHandles = false; + return false; + } + + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on + // RGBA8 textures/swapchains. + if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mSupportsShareHandles = false; + return false; + } + + // Find out which type of D3D11 device the Renderer11 is using + d3d11::ANGLED3D11DeviceType deviceType = getDeviceType(); + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN) + { + mSupportsShareHandles = false; + return false; + } + + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL) + { + // Software/Reference/NULL devices don't support share handles + mSupportsShareHandles = false; + return false; + } + + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP) + { +#ifndef ANGLE_ENABLE_WINDOWS_STORE + if (!IsWindows8OrGreater()) + { + // WARP on Windows 7 doesn't support shared handles + mSupportsShareHandles = false; + return false; + } +#endif // ANGLE_ENABLE_WINDOWS_STORE + + // WARP on Windows 8.0+ supports shared handles when shared with another WARP device + // TODO: allow applications to query for HARDWARE or WARP-specific share handles, + // to prevent them trying to use a WARP share handle with an a HW device (or + // vice-versa) + // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE + mSupportsShareHandles = true; + return true; + } + + ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE); + mSupportsShareHandles = true; + return true; +} + +bool Renderer11::getNV12TextureSupport() const +{ + HRESULT result; + UINT formatSupport; + result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport); + if (result == E_FAIL) + { + return false; + } + return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; +} + +int Renderer11::getMajorShaderModel() const +{ + switch (mRenderer11DeviceCaps.featureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_9_3: + return D3D10_SHADER_MAJOR_VERSION; // 4 + default: + UNREACHABLE(); + return 0; + } +} + +int Renderer11::getMinorShaderModel() const +{ + switch (mRenderer11DeviceCaps.featureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_SHADER_MINOR_VERSION; // 1 + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_9_3: + return D3D10_SHADER_MINOR_VERSION; // 0 + default: + UNREACHABLE(); + return 0; + } +} + +std::string Renderer11::getShaderModelSuffix() const +{ + switch (mRenderer11DeviceCaps.featureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return ""; + case D3D_FEATURE_LEVEL_10_1: + return ""; + case D3D_FEATURE_LEVEL_10_0: + return ""; + case D3D_FEATURE_LEVEL_9_3: + return "_level_9_3"; + default: + UNREACHABLE(); + return ""; + } +} + +const WorkaroundsD3D &RendererD3D::getWorkarounds() const +{ + if (!mWorkaroundsInitialized) + { + mWorkarounds = generateWorkarounds(); + mWorkaroundsInitialized = true; + } + + return mWorkarounds; +} + +gl::Error Renderer11::copyImageInternal(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget) +{ + const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer(); + ASSERT(colorAttachment); + + RenderTarget11 *sourceRenderTarget = nullptr; + ANGLE_TRY(colorAttachment->getRenderTarget(&sourceRenderTarget)); + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getBlitShaderResourceView(); + ASSERT(source); + + ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + const bool invertSource = UsePresentPathFast(this, colorAttachment); + if (invertSource) + { + sourceArea.y = sourceSize.height - sourceRect.y; + sourceArea.height = -sourceArea.height; + } + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct copy. + // Convert to the unsized format before calling copyTexture. + const gl::InternalFormat &internalFormat = gl::GetInternalFormatInfo(destFormat); + ANGLE_TRY(mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, nullptr, + internalFormat.format, GL_NEAREST, false, false, false)); + + return gl::NoError(); +} + +gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) +{ + TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget)); + + storage11->markLevelDirty(level); + + return gl::NoError(); +} + +gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level) +{ + TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget)); + + storage11->markLevelDirty(level); + + return gl::NoError(); +} + +gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) +{ + TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget)); + + storage11->markLevelDirty(level); + + return gl::NoError(); +} + +gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) +{ + TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget)); + storage11->markLevelDirty(level); + + return gl::NoError(); +} + +gl::Error Renderer11::copyTexture(const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage)); + + TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage); + ASSERT(sourceStorage11); + + TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage); + ASSERT(destStorage11); + + // Check for fast path where a CopySubresourceRegion can be used. + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY && + sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat) + { + ID3D11Resource *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(&sourceResource)); + + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(&destResource)); + + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); + + D3D11_BOX sourceBox{ + static_cast<UINT>(sourceRect.x), + static_cast<UINT>(sourceRect.y), + 0u, + static_cast<UINT>(sourceRect.x + sourceRect.width), + static_cast<UINT>(sourceRect.y + sourceRect.height), + 1u, + }; + + mDeviceContext->CopySubresourceRegion(destResource, destSubresource, destOffset.x, + destOffset.y, destOffset.z, sourceResource, + sourceSubresource, &sourceBox); + } + else + { + ID3D11ShaderResourceView *sourceSRV = nullptr; + ANGLE_TRY(sourceStorage11->getSRVLevels(sourceLevel, sourceLevel, &sourceSRV)); + + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); + RenderTargetD3D *destRenderTargetD3D = nullptr; + ANGLE_TRY(destStorage11->getRenderTarget(destIndex, &destRenderTargetD3D)); + + RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D); + + ID3D11RenderTargetView *destRTV = destRenderTarget11->getRenderTargetView(); + ASSERT(destRTV); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize( + static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)), + static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1); + if (unpackFlipY) + { + sourceArea.y = sourceSize.height - sourceRect.y; + sourceArea.height = -sourceArea.height; + } + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + ANGLE_TRY(mBlit->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, + nullptr, destFormat, GL_NEAREST, false, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha)); + } + + destStorage11->markLevelDirty(destLevel); + + return gl::NoError(); +} + +gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) +{ + TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage); + ASSERT(destStorage11); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(&destResource)); + + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); + + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ASSERT(sourceD3D); + + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage)); + + TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage); + ASSERT(sourceStorage11); + + ID3D11Resource *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(&sourceResource)); + + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); + + mDeviceContext->CopySubresourceRegion(destResource, destSubresource, 0, 0, 0, sourceResource, + sourceSubresource, nullptr); + + return gl::NoError(); +} + +UINT64 EstimateSize(D3D11_TEXTURE2D_DESC &desc) +{ + //XXX: handle overflow (64 bits should be enough for anyone...) + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(desc.Format); + // NVIDIA seems to align the width of buffers by 8 and the height by 64, so we do the same. + UINT64 total = UINT64(rx::roundUp(desc.Width, UINT(8))) * rx::roundUp(desc.Height, UINT(64)) * desc.SampleDesc.Count * dxgiFormatInfo.pixelBytes; + return total; +} + +gl::Error Renderer11::createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) +{ + const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps); + + const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + if (width > 0 && height > 0) + { + // Create texture resource + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = formatInfo.texFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN); + + // D3D feature level 10.0 no longer allows creation of textures with both the bind SRV and + // DSV flags when multisampled. crbug.com/656989 + bool supportsMultisampledDepthStencilSRVs = + mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0; + bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1; + if (isMultisampledDepthStencil && !supportsMultisampledDepthStencilSRVs) + { + bindSRV = false; + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); + + // The format must be either an RTV or a DSV + ASSERT(bindRTV != bindDSV); + + ID3D11Texture2D *texture = NULL; + HRESULT result; + + // Some Nvidia drivers (GeForce GT 610 w/ 9.18.13.3523) crash with very large render targets + if (EstimateSize(desc) > getMaxResourceSize()) + { + result = E_OUTOFMEMORY; + } + else + { + result = mDevice->CreateTexture2D(&desc, NULL, &texture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create render target texture, result: 0x%X.", result); + } + + ID3D11ShaderResourceView *srv = nullptr; + ID3D11ShaderResourceView *blitSRV = nullptr; + if (bindSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = formatInfo.srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + + result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to create render target shader resource view, result: 0x%X.", result); + } + + if (formatInfo.blitSRVFormat != formatInfo.srvFormat) + { + D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc; + blitSRVDesc.Format = formatInfo.blitSRVFormat; + blitSRVDesc.ViewDimension = (supportedSamples == 0) + ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; + blitSRVDesc.Texture2D.MostDetailedMip = 0; + blitSRVDesc.Texture2D.MipLevels = 1; + + result = mDevice->CreateShaderResourceView(texture, &blitSRVDesc, &blitSRV); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create render target shader resource view for " + "blits, result: 0x%X.", + result); + } + } + else + { + blitSRV = srv; + srv->AddRef(); + } + } + + if (bindDSV) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = formatInfo.dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D + : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv = NULL; + result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create render target depth stencil view, result: 0x%X.", + result); + } + + *outRT = new TextureRenderTarget11(dsv, texture, srv, format, formatInfo, width, height, + 1, supportedSamples); + + SafeRelease(dsv); + } + else if (bindRTV) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = formatInfo.rtvFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D + : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + + ID3D11RenderTargetView *rtv = NULL; + result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create render target render target view, result: 0x%X.", + result); + } + + if (formatInfo.dataInitializerFunction != NULL) + { + const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + mDeviceContext->ClearRenderTargetView(rtv, clearValues); + } + + *outRT = new TextureRenderTarget11(rtv, texture, srv, blitSRV, format, formatInfo, + width, height, 1, supportedSamples); + + SafeRelease(rtv); + } + else + { + UNREACHABLE(); + } + + SafeRelease(texture); + SafeRelease(srv); + SafeRelease(blitSRV); + } + else + { + *outRT = new TextureRenderTarget11( + static_cast<ID3D11RenderTargetView *>(nullptr), nullptr, nullptr, nullptr, format, + d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), width, height, 1, supportedSamples); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) +{ + ASSERT(source != nullptr); + + RenderTargetD3D *newRT = nullptr; + ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(), + source->getInternalFormat(), source->getSamples(), &newRT)); + + RenderTarget11 *source11 = GetAs<RenderTarget11>(source); + RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT); + + mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0, + 0, source11->getTexture(), + source11->getSubresourceIndex(), nullptr); + *outRT = newRT; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) +{ + switch (type) + { + case SHADER_VERTEX: + { + ID3D11VertexShader *vertexShader = NULL; + ID3D11GeometryShader *streamOutShader = NULL; + + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", + result); + } + + if (!streamOutVaryings.empty()) + { + std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; + soDeclaration.reserve(streamOutVaryings.size()); + + for (const auto &streamOutVarying : streamOutVaryings) + { + D3D11_SO_DECLARATION_ENTRY entry = {0}; + entry.Stream = 0; + entry.SemanticName = streamOutVarying.semanticName.c_str(); + entry.SemanticIndex = streamOutVarying.semanticIndex; + entry.StartComponent = 0; + entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount); + entry.OutputSlot = static_cast<BYTE>( + (separatedOutputBuffers ? streamOutVarying.outputSlot : 0)); + soDeclaration.push_back(entry); + } + + result = mDevice->CreateGeometryShaderWithStreamOutput( + function, static_cast<unsigned int>(length), soDeclaration.data(), + static_cast<unsigned int>(soDeclaration.size()), NULL, 0, 0, NULL, + &streamOutShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create steam output shader, result: 0x%X.", result); + } + } + + *outExecutable = + new ShaderExecutable11(function, length, vertexShader, streamOutShader); + } + break; + case SHADER_PIXEL: + { + ID3D11PixelShader *pixelShader = NULL; + + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", + result); + } + + *outExecutable = new ShaderExecutable11(function, length, pixelShader); + } + break; + case SHADER_GEOMETRY: + { + ID3D11GeometryShader *geometryShader = NULL; + + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create geometry shader, result: 0x%X.", result); + } + + *outExecutable = new ShaderExecutable11(function, length, geometryShader); + } + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) +{ + const char *profileType = NULL; + switch (type) + { + case SHADER_VERTEX: + profileType = "vs"; + break; + case SHADER_PIXEL: + profileType = "ps"; + break; + case SHADER_GEOMETRY: + profileType = "gs"; + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), + getMinorShaderModel(), getShaderModelSuffix().c_str()); + + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; + + if (gl::DebugAnnotationsActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + } + + if (workarounds.enableIEEEStrictness) + flags |= D3DCOMPILE_IEEE_STRICTNESS; + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders + // when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + std::vector<CompileConfig> configs; + configs.push_back(CompileConfig(flags, "default")); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation")); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); + + if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "") + { + // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader". + // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*. + // Using the [unroll] directive works around this, as does this D3DCompile flag. + configs.push_back( + CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); + } + + D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}}; + + ID3DBlob *binary = NULL; + std::string debugInfo; + ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, + &debugInfo)); + + // It's possible that binary is NULL if the compiler failed in all configurations. Set the + // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the + // internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } + + gl::Error error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + streamOutVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::NoError(); +} + +UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) +{ + return new UniformStorage11(this, storageSize); +} + +VertexBuffer *Renderer11::createVertexBuffer() +{ + return new VertexBuffer11(this); +} + +IndexBuffer *Renderer11::createIndexBuffer() +{ + return new IndexBuffer11(this); +} + +StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) +{ + return new StreamProducerNV12(this); +} + +bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + ASSERT(getNativeExtensions().pixelBufferObject); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + const d3d11::Format &d3d11FormatInfo = + d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps); + + // sRGB formats do not work with D3D11 buffer SRVs + if (internalFormatInfo.colorEncoding == GL_SRGB) + { + return false; + } + + // We cannot support direct copies to non-color-renderable formats + if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN) + { + return false; + } + + // We skip all 3-channel formats since sometimes format support is missing + if (internalFormatInfo.componentCount == 3) + { + return false; + } + + // We don't support formats which we can't represent without conversion + if (d3d11FormatInfo.format().glInternalFormat != internalFormat) + { + return false; + } + + // Buffer SRV creation for this format was not working on Windows 10. + if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM) + { + return false; + } + + // This format is not supported as a buffer SRV. + if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM) + { + return false; + } + + return true; +} + +gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) +{ + ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); + return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, + sourcePixelsType, destArea); +} + +ImageD3D *Renderer11::createImage() +{ + return new Image11(this); +} + +gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) +{ + Image11 *dest11 = GetAs<Image11>(dest); + Image11 *src11 = GetAs<Image11>(src); + return Image11::generateMipmap(dest11, src11, mRenderer11DeviceCaps); +} + +gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) +{ + TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); + + ASSERT(storage11->isRenderTarget()); + ASSERT(storage11->supportsNativeMipmapFunction()); + + ID3D11ShaderResourceView *srv; + ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(), + textureState.getEffectiveMaxLevel(), &srv)); + + mDeviceContext->GenerateMips(srv); + + return gl::NoError(); +} + +TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) +{ + SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain); + return new TextureStorage11_2D(this, swapChain11); +} + +TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) +{ + return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D)); +} + +TextureStorage *Renderer11::createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + return new TextureStorage11_External(this, stream, desc); +} + +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) +{ + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, + hintLevelZeroOnly); +} + +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) +{ + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, + hintLevelZeroOnly); +} + +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) +{ + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, + levels); +} + +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) +{ + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, + levels); +} + +gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + const gl::Rectangle &sourceArea, + GLenum format, + GLenum type, + GLuint outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixelsOut) +{ + ASSERT(sourceArea.width >= 0); + ASSERT(sourceArea.height >= 0); + + const bool invertTexture = UsePresentPathFast(this, &srcAttachment); + + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(srcAttachment.getRenderTarget(&renderTarget)); + + RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); + ASSERT(rt11->getTexture()); + + TextureHelper11 textureHelper = + TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet()); + unsigned int sourceSubResource = rt11->getSubresourceIndex(); + + const gl::Extents &texSize = textureHelper.getExtents(); + + gl::Rectangle actualArea = sourceArea; + if (invertTexture) + { + actualArea.y = texSize.height - actualArea.y - actualArea.height; + } + + // Clamp read region to the defined texture boundaries, preventing out of bounds reads + // and reads of uninitialized data. + gl::Rectangle safeArea; + safeArea.x = gl::clamp(actualArea.x, 0, texSize.width); + safeArea.y = gl::clamp(actualArea.y, 0, texSize.height); + safeArea.width = + gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x); + safeArea.height = + gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y); + + ASSERT(safeArea.x >= 0 && safeArea.y >= 0); + ASSERT(safeArea.x + safeArea.width <= texSize.width); + ASSERT(safeArea.y + safeArea.height <= texSize.height); + + if (safeArea.width == 0 || safeArea.height == 0) + { + // no work to do + return gl::NoError(); + } + + gl::Extents safeSize(safeArea.width, safeArea.height, 1); + TextureHelper11 stagingHelper; + ANGLE_TRY_RESULT( + CreateStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize, + StagingAccess::READ, mDevice), + stagingHelper); + + TextureHelper11 resolvedTextureHelper; + + // "srcTexture" usually points to the source texture. + // For 2D multisampled textures, it points to the multisampled resolve texture. + const TextureHelper11 *srcTexture = &textureHelper; + + if (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = static_cast<UINT>(texSize.width); + resolveDesc.Height = static_cast<UINT>(texSize.height); + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureHelper.getFormat(); + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTex2D = nullptr; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Renderer11::readTextureData failed to create internal resolve " + "texture for ReadPixels, HRESULT: 0x%X.", + result); + } + + mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(), + sourceSubResource, textureHelper.getFormat()); + resolvedTextureHelper = + TextureHelper11::MakeAndReference(resolveTex2D, textureHelper.getFormatSet()); + + sourceSubResource = 0; + srcTexture = &resolvedTextureHelper; + } + + D3D11_BOX srcBox; + srcBox.left = static_cast<UINT>(safeArea.x); + srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width); + srcBox.top = static_cast<UINT>(safeArea.y); + srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height); + + // Select the correct layer from a 3D attachment + srcBox.front = 0; + if (textureHelper.getTextureType() == GL_TEXTURE_3D) + { + srcBox.front = static_cast<UINT>(srcAttachment.layer()); + } + srcBox.back = srcBox.front + 1; + + mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0, + srcTexture->getResource(), sourceSubResource, &srcBox); + + if (!invertTexture) + { + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + return packPixels(stagingHelper, packParams, pixelsOut); + } + + gl::PixelPackState invertTexturePack; + + // Create a new PixelPackState with reversed row order. Note that we can't just assign + // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object + // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use + // pixelBuffer.set() twice, which performs the addRef/release correctly + invertTexturePack.alignment = pack.alignment; + invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get()); + invertTexturePack.reverseRowOrder = !pack.reverseRowOrder; + + PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0); + gl::Error error = packPixels(stagingHelper, packParams, pixelsOut); + invertTexturePack.pixelBuffer.set(nullptr); + ANGLE_TRY(error); + return gl::NoError(); +} + +gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper, + const PackPixelsParams ¶ms, + uint8_t *pixelsOut) +{ + ID3D11Resource *readResource = textureHelper.getResource(); + + D3D11_MAPPED_SUBRESOURCE mapping; + HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping); + if (FAILED(hr)) + { + ASSERT(hr == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal texture for reading, result: 0x%X.", hr); + } + + uint8_t *source = static_cast<uint8_t *>(mapping.pData); + int inputPitch = static_cast<int>(mapping.RowPitch); + + const auto &formatInfo = textureHelper.getFormatSet(); + ASSERT(formatInfo.format().glInternalFormat != GL_NONE); + + PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut); + + mDeviceContext->Unmap(readResource, 0); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, + const gl::Rectangle &drawRectIn, + RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, + GLenum filter, + const gl::Rectangle *scissor, + bool colorBlit, + bool depthBlit, + bool stencilBlit) +{ + // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, + // it should never be the case that both color and depth/stencil need to be blitted at + // at the same time. + ASSERT(colorBlit != (depthBlit || stencilBlit)); + + RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget); + if (!drawRenderTarget11) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to retrieve the internal draw render target from the draw framebuffer."); + } + + TextureHelper11 drawTexture = TextureHelper11::MakeAndReference( + drawRenderTarget11->getTexture(), drawRenderTarget11->getFormatSet()); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); + ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); + + RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget); + if (!readRenderTarget11) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to retrieve the internal read render target from the read framebuffer."); + } + + TextureHelper11 readTexture; + unsigned int readSubresource = 0; + ID3D11ShaderResourceView *readSRV = nullptr; + + if (readRenderTarget->getSamples() > 1) + { + auto readRT11 = GetAs<RenderTarget11>(readRenderTarget); + ANGLE_TRY_RESULT(resolveMultisampledTexture(readRT11, depthBlit, stencilBlit), readTexture); + + if (!stencilBlit) + { + const auto &readFormatSet = readTexture.getFormatSet(); + + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + viewDesc.Format = readFormatSet.srvFormat; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = 1; + viewDesc.Texture2D.MostDetailedMip = 0; + + HRESULT hresult = + mDevice->CreateShaderResourceView(readTexture.getResource(), &viewDesc, &readSRV); + if (FAILED(hresult)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Renderer11::blitRenderbufferRect: Failed to create temporary SRV."); + } + } + } + else + { + ASSERT(readRenderTarget11); + readTexture = TextureHelper11::MakeAndReference(readRenderTarget11->getTexture(), + readRenderTarget11->getFormatSet()); + readSubresource = readRenderTarget11->getSubresourceIndex(); + readSRV = readRenderTarget11->getBlitShaderResourceView(); + if (readSRV == nullptr) + { + ASSERT(depthBlit || stencilBlit); + readSRV = readRenderTarget11->getShaderResourceView(); + } + ASSERT(readSRV); + readSRV->AddRef(); + } + + // Stencil blits don't use shaders. + ASSERT(readSRV || stencilBlit); + + const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + // From the spec: + // "The actual region taken from the read framebuffer is limited to the intersection of the + // source buffers being transferred, which may include the color buffer selected by the read + // buffer, the depth buffer, and / or the stencil buffer depending on mask." + // This means negative x and y are out of bounds, and not to be read from. We handle this here + // by internally scaling the read and draw rectangles. + gl::Rectangle readRect = readRectIn; + gl::Rectangle drawRect = drawRectIn; + auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) { + double readToDrawScale = + static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width); + return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale)); + }; + if (readRect.x < 0) + { + int readOffset = -readRect.x; + readRect.x += readOffset; + readRect.width -= readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.x += drawOffset; + drawRect.width -= drawOffset; + } + + auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) { + double readToDrawScale = + static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height); + return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale)); + }; + if (readRect.y < 0) + { + int readOffset = -readRect.y; + readRect.y += readOffset; + readRect.height -= readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.y += drawOffset; + drawRect.height -= drawOffset; + } + + if (readRect.x1() < 0) + { + int readOffset = -readRect.x1(); + readRect.width += readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.width += drawOffset; + } + + if (readRect.y1() < 0) + { + int readOffset = -readRect.y1(); + readRect.height += readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.height += drawOffset; + } + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr); + + const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()); + const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat()); + const auto &formatSet = drawRenderTarget11->getFormatSet(); + const auto &nativeFormat = formatSet.format(); + + // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we + // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy. + + gl::Color<bool> colorMask; + colorMask.red = + (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0); + colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && + (nativeFormat.greenBits > 0); + colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && + (nativeFormat.blueBits > 0); + colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && + (nativeFormat.alphaBits > 0); + + // We only currently support masking off the alpha channel. + bool colorMaskingNeeded = colorMask.alpha; + ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue); + + bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 && + readRect.width == readSize.width && readRect.y == 0 && + readRect.height == readSize.height && drawRect.x == 0 && + drawRect.width == drawSize.width && drawRect.y == 0 && + drawRect.height == drawSize.height; + + bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; + + bool flipRequired = + readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; + + bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || + readRect.y < 0 || readRect.y + readRect.height > readSize.height || + drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || + drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; + + bool partialDSBlit = + (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit); + + if (readRenderTarget11->getFormatSet().formatID == + drawRenderTarget11->getFormatSet().formatID && + !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && + !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) + { + UINT dstX = drawRect.x; + UINT dstY = drawRect.y; + + D3D11_BOX readBox; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; + readBox.bottom = readRect.y + readRect.height; + readBox.front = 0; + readBox.back = 1; + + if (scissorNeeded) + { + // drawRect is guaranteed to have positive width and height because stretchRequired is + // false. + ASSERT(drawRect.width >= 0 || drawRect.height >= 0); + + if (drawRect.x < scissor->x) + { + dstX = scissor->x; + readBox.left += (scissor->x - drawRect.x); + } + if (drawRect.y < scissor->y) + { + dstY = scissor->y; + readBox.top += (scissor->y - drawRect.y); + } + if (drawRect.x + drawRect.width > scissor->x + scissor->width) + { + readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); + } + if (drawRect.y + drawRect.height > scissor->y + scissor->height) + { + readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); + } + } + + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox + // We also require complete framebuffer copies for depth-stencil blit. + D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox; + + mDeviceContext->CopySubresourceRegion(drawTexture.getResource(), drawSubresource, dstX, + dstY, 0, readTexture.getResource(), readSubresource, + pSrcBox); + } + else + { + gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); + gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); + + if (depthBlit && stencilBlit) + { + ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); + } + else if (depthBlit) + { + ASSERT(readSRV); + ANGLE_TRY(mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, + scissor)); + } + else if (stencilBlit) + { + ANGLE_TRY(mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); + } + else + { + // We don't currently support masking off any other channel than alpha + bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha; + ASSERT(readSRV); + ANGLE_TRY(mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, + scissor, destFormatInfo.format, filter, maskOffAlpha, + false, false)); + } + } + + SafeRelease(readSRV); + + return gl::NoError(); +} + +bool Renderer11::isES3Capable() const +{ + return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2); +}; + +void Renderer11::onSwap() +{ + // Send histogram updates every half hour + const double kHistogramUpdateInterval = 30 * 60; + + const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime(); + const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; + + if (timeSinceLastUpdate > kHistogramUpdateInterval) + { + updateHistograms(); + mLastHistogramUpdateTime = currentTime; + } +} + +void Renderer11::updateHistograms() +{ + // Update the buffer CPU memory histogram + { + size_t sizeSum = 0; + for (auto &buffer : mAliveBuffers) + { + sizeSum += buffer->getTotalCPUBufferMemoryBytes(); + } + const int kOneMegaByte = 1024 * 1024; + ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB", + static_cast<int>(sizeSum) / kOneMegaByte); + } +} + +void Renderer11::onBufferCreate(const Buffer11 *created) +{ + mAliveBuffers.insert(created); +} + +void Renderer11::onBufferDelete(const Buffer11 *deleted) +{ + mAliveBuffers.erase(deleted); +} + +gl::ErrorOrResult<TextureHelper11> +Renderer11::resolveMultisampledTexture(RenderTarget11 *renderTarget, bool depth, bool stencil) +{ + if (depth && !stencil) + { + return mBlit->resolveDepth(renderTarget); + } + + if (stencil) + { + return mBlit->resolveStencil(renderTarget, depth); + } + + const auto &formatSet = renderTarget->getFormatSet(); + + ASSERT(renderTarget->getSamples() > 1); + + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = renderTarget->getWidth(); + resolveDesc.Height = renderTarget->getHeight(); + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = formatSet.texFormat; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTexture = nullptr; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTexture); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); + } + + mDeviceContext->ResolveSubresource(resolveTexture, 0, renderTarget->getTexture(), + renderTarget->getSubresourceIndex(), formatSet.texFormat); + return TextureHelper11::MakeAndPossess2D(resolveTexture, renderTarget->getFormatSet()); +} + +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + +VertexConversionType Renderer11::getVertexConversionType( + gl::VertexFormatType vertexFormatType) const +{ + return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel) + .conversionType; +} + +GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const +{ + const auto &format = + d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel); + return d3d11::GetComponentType(format.nativeFormat); +} + +gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired( + const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const +{ + if (!attrib.enabled) + { + return 16u; + } + + unsigned int elementCount = 0; + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor); + } + + gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib); + const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = + d3d11::GetVertexFormatInfo(formatType, featureLevel); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat); + unsigned int elementSize = dxgiFormatInfo.pixelBytes; + if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount) + { + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); + } + + return elementSize * elementCount; +} + +void Renderer11::generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const +{ + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, + outExtensions, outLimitations); +} + +WorkaroundsD3D Renderer11::generateWorkarounds() const +{ + return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription); +} + +gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +{ + return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd); +} + +egl::Error Renderer11::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) + { + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice), + EGL_D3D11_DEVICE_ANGLE, EGL_FALSE); + + if (error.isError()) + { + SafeDelete(mEGLDevice); + return error; + } + } + + *device = static_cast<DeviceImpl *>(mEGLDevice); + return egl::Error(EGL_SUCCESS); +} + +ContextImpl *Renderer11::createContext(const gl::ContextState &state) +{ + return new Context11(state, this); +} + +gl::Error Renderer11::genericDrawElements(Context11 *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + const auto &data = context->getContextState(); + const auto &glState = data.getState(); + gl::Program *program = glState.getProgram(); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + bool usesPointSize = programD3D->usesPointSize(); + + programD3D->updateSamplerMapping(); + + ANGLE_TRY(generateSwizzles(data)); + + if (!applyPrimitiveType(mode, count, usesPointSize)) + { + return gl::NoError(); + } + + ANGLE_TRY(updateState(data, mode)); + + TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; + + ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo)); + + applyTransformFeedbackBuffers(data); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the + // API validation layer. + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); + + size_t vertexCount = indexInfo.indexRange.vertexCount(); + ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexInfo.indexRange.start), + static_cast<GLsizei>(vertexCount), instances, &indexInfo)); + ANGLE_TRY(applyTextures(context, data)); + ANGLE_TRY(applyShaders(data, mode)); + ANGLE_TRY(programD3D->applyUniformBuffers(data)); + + if (!skipDraw(data, mode)) + { + ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances)); + } + + return gl::NoError(); +} + +gl::Error Renderer11::genericDrawArrays(Context11 *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances) +{ + const auto &data = context->getContextState(); + const auto &glState = data.getState(); + gl::Program *program = glState.getProgram(); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + bool usesPointSize = programD3D->usesPointSize(); + + programD3D->updateSamplerMapping(); + + ANGLE_TRY(generateSwizzles(data)); + if (!applyPrimitiveType(mode, count, usesPointSize)) + { + return gl::NoError(); + } + + ANGLE_TRY(updateState(data, mode)); + ANGLE_TRY(applyTransformFeedbackBuffers(data)); + ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr)); + ANGLE_TRY(applyTextures(context, data)); + ANGLE_TRY(applyShaders(data, mode)); + ANGLE_TRY(programD3D->applyUniformBuffers(data)); + + if (!skipDraw(data, mode)) + { + ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances)); + + if (glState.isTransformFeedbackActiveUnpaused()) + { + ANGLE_TRY(markTransformFeedbackUsage(data)); + } + } + + return gl::NoError(); +} + +FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + return new Framebuffer11(state, this); +} + +gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut) +{ + if (mScratchMemoryBuffer.size() == requestedSize) + { + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + *bufferOut = &mScratchMemoryBuffer; + return gl::NoError(); + } + + if (mScratchMemoryBuffer.size() > requestedSize) + { + mScratchMemoryBufferResetCounter--; + } + + if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize) + { + mScratchMemoryBuffer.resize(0); + if (!mScratchMemoryBuffer.resize(requestedSize)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + } + + ASSERT(mScratchMemoryBuffer.size() >= requestedSize); + + *bufferOut = &mScratchMemoryBuffer; + return gl::NoError(); +} + +gl::Version Renderer11::getMaxSupportedESVersion() const +{ + return gl::Version(d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel), 0); +} + +gl::DebugAnnotator *Renderer11::getAnnotator() +{ + return mAnnotator; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h new file mode 100755 index 000000000..576fe3215 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -0,0 +1,580 @@ +// +// 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.h: Defines a back-end specific class for the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" + +namespace gl +{ +class FramebufferAttachment; +struct ImageIndex; +} + +namespace rx +{ +class Blit11; +class Buffer11; +class Clear11; +class Context11; +class IndexDataManager; +struct PackPixelsParams; +class PixelTransfer11; +class RenderTarget11; +class StreamingIndexBufferInterface; +class Trim11; +class VertexDataManager; + +struct Renderer11DeviceCaps +{ + D3D_FEATURE_LEVEL featureLevel; + bool supportsDXGI1_2; // Support for DXGI 1.2 + bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView + bool supportsConstantBufferOffsets; // Support for Constant buffer offset + UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM + UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM + UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM + Optional<LARGE_INTEGER> driverVersion; // Four-part driver version number. +}; + +enum +{ + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 +}; + +// Possible reasons RendererD3D initialize can fail +enum D3D11InitError +{ + // The renderer loaded successfully + D3D11_INIT_SUCCESS = 0, + // Failed to load the ANGLE & D3D compiler libraries + D3D11_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL (non-compiler) + D3D11_INIT_MISSING_DEP, + // CreateDevice returned E_INVALIDARG + D3D11_INIT_CREATEDEVICE_INVALIDARG, + // CreateDevice failed with an error other than invalid arg + D3D11_INIT_CREATEDEVICE_ERROR, + // DXGI 1.2 required but not found + D3D11_INIT_INCOMPATIBLE_DXGI, + // Other initialization error + D3D11_INIT_OTHER_ERROR, + // CreateDevice returned E_FAIL + D3D11_INIT_CREATEDEVICE_FAIL, + // CreateDevice returned E_NOTIMPL + D3D11_INIT_CREATEDEVICE_NOTIMPL, + // CreateDevice returned E_OUTOFMEMORY + D3D11_INIT_CREATEDEVICE_OUTOFMEMORY, + // CreateDevice returned DXGI_ERROR_INVALID_CALL + D3D11_INIT_CREATEDEVICE_INVALIDCALL, + // CreateDevice returned DXGI_ERROR_SDK_COMPONENT_MISSING + D3D11_INIT_CREATEDEVICE_COMPONENTMISSING, + // CreateDevice returned DXGI_ERROR_WAS_STILL_DRAWING + D3D11_INIT_CREATEDEVICE_WASSTILLDRAWING, + // CreateDevice returned DXGI_ERROR_NOT_CURRENTLY_AVAILABLE + D3D11_INIT_CREATEDEVICE_NOTAVAILABLE, + // CreateDevice returned DXGI_ERROR_DEVICE_HUNG + D3D11_INIT_CREATEDEVICE_DEVICEHUNG, + // CreateDevice returned NULL + D3D11_INIT_CREATEDEVICE_NULL, + NUM_D3D11_INIT_ERRORS +}; + +class Renderer11 : public RendererD3D +{ + public: + explicit Renderer11(egl::Display *display); + virtual ~Renderer11(); + + egl::Error initialize() override; + bool resetDevice() override; + + egl::ConfigSet generateConfigs() override; + void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; + + ContextImpl *createContext(const gl::ContextState &state) override; + + gl::Error flush(); + gl::Error finish(); + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const override; + + SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; + egl::Error getD3DTextureInfo(IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const override; + egl::Error validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const override; + + gl::Error setSamplerState(gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &sampler) override; + gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override; + + gl::Error setUniformBuffers(const gl::ContextState &data, + const std::vector<GLint> &vertexUniformBuffers, + const std::vector<GLint> &fragmentUniformBuffers) override; + + gl::Error updateState(const gl::ContextState &data, GLenum drawMode); + + bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize); + gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer); + gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector<D3DUniform *> &uniformArray) override; + gl::Error applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo); + gl::Error applyIndexBuffer(const gl::ContextState &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo); + gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data); + + // lost device + bool testDeviceLost() override; + bool testDeviceResettable() override; + + SIZE_T getMaxResourceSize() const; + std::string getRendererDescription() const; + DeviceIdentifier getAdapterIdentifier() const override; + + unsigned int getReservedVertexUniformVectors() const; + unsigned int getReservedFragmentUniformVectors() const; + unsigned int getReservedVertexUniformBuffers() const override; + unsigned int getReservedFragmentUniformBuffers() const override; + + bool getShareHandleSupport() const; + + bool getNV12TextureSupport() const; + + int getMajorShaderModel() const override; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; + + // Pixel operations + gl::Error copyImage2D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImageCube(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level) override; + gl::Error copyImage3D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + + gl::Error copyTexture(const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + gl::Error copyCompressedTexture(const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) override; + + // RenderTarget creation + gl::Error createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) override; + gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; + + // Shader operations + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; + + // Image operations + ImageD3D *createImage() override; + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) override; + TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override; + TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) override; + TextureStorage *createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + TextureStorage *createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + TextureStorage *createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + + VertexBuffer *createVertexBuffer() override; + IndexBuffer *createIndexBuffer() override; + + // Stream Creation + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; + + // D3D11-renderer specific methods + ID3D11Device *getDevice() { return mDevice; } + void *getD3DDevice() override; + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }; + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + + RenderStateCache &getStateCache() { return mStateCache; } + + Blit11 *getBlitter() { return mBlit; } + Clear11 *getClearer() { return mClear; } + gl::DebugAnnotator *getAnnotator(); + + // Buffer-to-texture and Texture-to-buffer copies + bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override; + gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) override; + + void markAllStateDirty(); + gl::Error packPixels(const TextureHelper11 &textureHelper, + const PackPixelsParams ¶ms, + uint8_t *pixelsOut); + + bool getLUID(LUID *adapterLuid) const override; + VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; + gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const override; + + gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + const gl::Rectangle &sourceArea, + GLenum format, + GLenum type, + GLuint outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels); + + gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); + + bool isES3Capable() const; + const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }; + + RendererClass getRendererClass() const override { return RENDERER_D3D11; } + InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + StateManager11 *getStateManager() { return &mStateManager; } + + void onSwap(); + void onBufferCreate(const Buffer11 *created); + void onBufferDelete(const Buffer11 *deleted); + + egl::Error getEGLDevice(DeviceImpl **device) override; + + gl::Error genericDrawArrays(Context11 *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances); + + gl::Error genericDrawElements(Context11 *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange); + + // Necessary hack for default framebuffers in D3D. + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); + + gl::Version getMaxSupportedESVersion() const override; + + protected: + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; + + private: + gl::Error drawArraysImpl(const gl::ContextState &data, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances); + gl::Error drawElementsImpl(const gl::ContextState &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances); + + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const override; + + WorkaroundsD3D generateWorkarounds() const override; + + gl::Error drawLineLoop(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + const TranslatedIndexData *indexInfo, + int instances); + gl::Error drawTriangleFan(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances); + + gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode); + gl::Error generateSwizzle(gl::Texture *texture); + gl::Error generateSwizzles(const gl::ContextState &data, gl::SamplerType type); + gl::Error generateSwizzles(const gl::ContextState &data); + + gl::ErrorOrResult<TextureHelper11> resolveMultisampledTexture(RenderTarget11 *renderTarget, + bool depth, + bool stencil); + + void populateRenderer11DeviceCaps(); + + void updateHistograms(); + + class SamplerMetadataD3D11 final : angle::NonCopyable + { + public: + SamplerMetadataD3D11(); + ~SamplerMetadataD3D11(); + + struct dx_SamplerMetadata + { + int baseLevel; + int internalFormatBits; + int wrapModes; + int padding; // This just pads the struct to 16 bytes + }; + static_assert(sizeof(dx_SamplerMetadata) == 16u, + "Sampler metadata struct must be one 4-vec / 16 bytes."); + + void initData(unsigned int samplerCount); + void update(unsigned int samplerIndex, const gl::Texture &texture); + + const dx_SamplerMetadata *getData() const; + size_t sizeBytes() const; + bool isDirty() const { return mDirty; } + void markClean() { mDirty = false; } + + private: + std::vector<dx_SamplerMetadata> mSamplerMetadata; + bool mDirty; + }; + + template <class TShaderConstants> + void applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants, + const TShaderConstants &constants, + SamplerMetadataD3D11 *samplerMetadata, + size_t samplerMetadataReferencedBytes, + ID3D11Buffer *driverConstantBuffer); + + gl::Error copyImageInternal(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget); + + HMODULE mD3d11Module; + HMODULE mDxgiModule; + HMODULE mDCompModule; + std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels; + D3D_DRIVER_TYPE mRequestedDriverType; + bool mCreatedWithDeviceEXT; + DeviceD3D *mEGLDevice; + + HLSLCompiler mCompiler; + + egl::Error initializeD3DDevice(); + void initializeDevice(); + void releaseDeviceResources(); + void release(); + + d3d11::ANGLED3D11DeviceType getDeviceType() const; + + RenderStateCache mStateCache; + + // Currently applied sampler states + std::vector<bool> mForceSetVertexSamplerStates; + std::vector<gl::SamplerState> mCurVertexSamplerStates; + + std::vector<bool> mForceSetPixelSamplerStates; + std::vector<gl::SamplerState> mCurPixelSamplerStates; + + StateManager11 mStateManager; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; + unsigned int mAppliedIBOffset; + bool mAppliedIBChanged; + + // Currently applied transform feedback buffers + uintptr_t mAppliedTFObject; + + // Currently applied shaders + uintptr_t mAppliedVertexShader; + uintptr_t mAppliedGeometryShader; + uintptr_t mAppliedPixelShader; + + dx_VertexConstants11 mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + SamplerMetadataD3D11 mSamplerMetadataVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; + unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + + dx_PixelConstants11 mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + SamplerMetadataD3D11 mSamplerMetadataPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; + + // Vertex, index and input layouts + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + InputLayoutCache mInputLayoutCache; + + StreamingIndexBufferInterface *mLineLoopIB; + StreamingIndexBufferInterface *mTriangleFanIB; + + // Texture copy resources + Blit11 *mBlit; + PixelTransfer11 *mPixelTransfer; + + // Masked clear resources + Clear11 *mClear; + + // Perform trim for D3D resources + Trim11 *mTrim; + + // Sync query + ID3D11Query *mSyncQuery; + + // Created objects state tracking + std::set<const Buffer11*> mAliveBuffers; + + double mLastHistogramUpdateTime; + + ID3D11Device *mDevice; + Renderer11DeviceCaps mRenderer11DeviceCaps; + ID3D11DeviceContext *mDeviceContext; + ID3D11DeviceContext1 *mDeviceContext1; + IDXGIAdapter *mDxgiAdapter; + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + IDXGIFactory *mDxgiFactory; + ID3D11Debug *mDebug; + + std::vector<GLuint> mScratchIndexDataBuffer; + + MemoryBuffer mScratchMemoryBuffer; + unsigned int mScratchMemoryBufferResetCounter; + + gl::DebugAnnotator *mAnnotator; + + mutable Optional<bool> mSupportsShareHandles; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp new file mode 100755 index 000000000..e20b161ef --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -0,0 +1,97 @@ +// +// 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. +// + +// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader +// executable implementation details. + +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) + : ShaderExecutableD3D(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) + : ShaderExecutableD3D(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = streamOut; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) + : ShaderExecutableD3D(function, length) +{ + mGeometryExecutable = executable; + mVertexExecutable = NULL; + mPixelExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::~ShaderExecutable11() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); + SafeRelease(mGeometryExecutable); + SafeRelease(mStreamOutExecutable); +} + +ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +{ + return mVertexExecutable; +} + +ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +{ + return mPixelExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +{ + return mGeometryExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const +{ + return mStreamOutExecutable; +} + +UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) + : UniformStorageD3D(initialSize), + mConstantBuffer(NULL) +{ + ID3D11Device *d3d11Device = renderer->getDevice(); + + if (initialSize > 0) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = static_cast<unsigned int>(initialSize); + constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + ASSERT(SUCCEEDED(result)); + } +} + +UniformStorage11::~UniformStorage11() +{ + SafeRelease(mConstantBuffer); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h new file mode 100755 index 000000000..379f39fe5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -0,0 +1,55 @@ +// +// 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. +// + +// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader +// executable implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +namespace rx +{ +class Renderer11; +class UniformStorage11; + +class ShaderExecutable11 : public ShaderExecutableD3D +{ + public: + ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); + ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); + + virtual ~ShaderExecutable11(); + + ID3D11PixelShader *getPixelShader() const; + ID3D11VertexShader *getVertexShader() const; + ID3D11GeometryShader *getGeometryShader() const; + ID3D11GeometryShader *getStreamOutShader() const; + + private: + ID3D11PixelShader *mPixelExecutable; + ID3D11VertexShader *mVertexExecutable; + ID3D11GeometryShader *mGeometryExecutable; + ID3D11GeometryShader *mStreamOutExecutable; +}; + +class UniformStorage11 : public UniformStorageD3D +{ + public: + UniformStorage11(Renderer11 *renderer, size_t initialSize); + virtual ~UniformStorage11(); + + ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + + private: + ID3D11Buffer *mConstantBuffer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp new file mode 100755 index 000000000..0e28c8c18 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -0,0 +1,1120 @@ +// +// 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/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.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 = NULL; + ASSERT(view); + view->GetResource(&resource); + resource->Release(); + return resource; +} + +} // anonymous namespace + +void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) +{ + ASSERT(resourceIndex < mCurrentSRVs.size()); + SRVRecord *record = &mCurrentSRVs[resourceIndex]; + + record->srv = reinterpret_cast<uintptr_t>(srv); + if (srv) + { + record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv)); + srv->GetDesc(&record->desc); + mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV); + } + else + { + record->resource = 0; + + if (resourceIndex + 1 == mHighestUsedSRV) + { + do + { + --mHighestUsedSRV; + } while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0); + } + } +} + +void StateManager11::SRVCache::clear() +{ + if (mCurrentSRVs.empty()) + { + return; + } + + memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size()); + mHighestUsedSRV = 0; +} + +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), + mBlendStateIsDirty(false), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mDepthStencilStateIsDirty(false), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurStencilSize(0), + mRasterizerStateIsDirty(false), + mScissorStateIsDirty(false), + mCurScissorEnabled(false), + mCurScissorRect(), + mViewportStateIsDirty(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mViewportBounds(), + mRenderTargetIsDirty(false), + mDirtyCurrentValueAttribs(), + mCurrentValueAttribs() +{ + 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_BACK; + mCurRasterState.frontFace = GL_CCW; + mCurRasterState.polygonOffsetFill = false; + mCurRasterState.polygonOffsetFactor = 0.0f; + mCurRasterState.polygonOffsetUnits = 0.0f; + mCurRasterState.pointDrawMode = false; + mCurRasterState.multiSample = false; + + // Initially all current value attributes must be updated on first use. + mDirtyCurrentValueAttribs.flip(); +} + +StateManager11::~StateManager11() +{ +} + +void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mDepthStencilStateIsDirty = true; + } +} + +void StateManager11::setViewportBounds(const int width, const int height) +{ + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && + (mViewportBounds.width != width || mViewportBounds.height != height)) + { + mViewportBounds = gl::Extents(width, height, 1); + mViewportStateIsDirty = true; + } +} + +void StateManager11::updatePresentPath(bool presentPathFastActive, + const gl::FramebufferAttachment *framebufferAttachment) +{ + const int colorBufferHeight = + framebufferAttachment ? framebufferAttachment->getSize().height : 0; + + if ((mCurPresentPathFastEnabled != presentPathFastActive) || + (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight))) + { + mCurPresentPathFastEnabled = presentPathFastActive; + mCurPresentPathFastColorBufferHeight = colorBufferHeight; + mViewportStateIsDirty = true; // Viewport may need to be vertically inverted + mScissorStateIsDirty = true; // Scissor rect may need to be vertically inverted + mRasterizerStateIsDirty = true; // Cull Mode may need to be inverted + } +} + +void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + if (!dirtyBits.any()) + { + return; + } + + for (auto dirtyBit : angle::IterateBitSet(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) + { + mBlendStateIsDirty = true; + } + 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) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mBlendStateIsDirty = true; + } + 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) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDepthStencilStateIsDirty = true; + } + 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) + { + mDepthStencilStateIsDirty = true; + } + 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) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDepthStencilStateIsDirty = true; + } + 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) + { + mDepthStencilStateIsDirty = true; + } + 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) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterState = state.getRasterizerState(); + if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mRasterizerStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: + if (state.getRasterizerState().rasterizerDiscard != + mCurRasterState.rasterizerDiscard) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mScissorStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mScissorStateIsDirty = true; + // Rasterizer state update needs mCurScissorsEnabled and updates when it changes + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mViewportStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mViewportStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: + mRenderTargetIsDirty = true; + break; + default: + if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && + dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX) + { + size_t attribIndex = + static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0); + mDirtyCurrentValueAttribs.set(attribIndex); + } + break; + } + } +} + +gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + if (!mBlendStateIsDirty && sampleMask == mCurSampleMask) + { + return gl::NoError(); + } + + ID3D11BlendState *dxBlendState = nullptr; + ANGLE_TRY(mRenderer->getStateCache().getBlendState(framebuffer, blendState, &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, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + + mBlendStateIsDirty = false; + + return gl::NoError(); +} + +gl::Error StateManager11::setDepthStencilState(const gl::State &glState) +{ + const auto &fbo = *glState.getDrawFramebuffer(); + + // 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()); + + // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. + if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && + disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && + disableStencil == mCurDisableStencil.value()) + { + return gl::NoError(); + } + + const auto &depthStencilState = glState.getDepthStencilState(); + int stencilRef = glState.getStencilRef(); + int stencilBackRef = glState.getStencilBackRef(); + + // get the maximum size of the stencil ref + unsigned int maxStencil = 0; + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + maxStencil = (1 << mCurStencilSize) - 1; + } + ASSERT((depthStencilState.stencilWritemask & maxStencil) == + (depthStencilState.stencilBackWritemask & maxStencil)); + ASSERT(stencilRef == stencilBackRef); + ASSERT((depthStencilState.stencilMask & maxStencil) == + (depthStencilState.stencilBackMask & maxStencil)); + + ID3D11DepthStencilState *dxDepthStencilState = NULL; + ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState( + depthStencilState, disableDepth, disableStencil, &dxDepthStencilState)); + + 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 + 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>(stencilRef, 0xFFu); + + mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurDisableDepth = disableDepth; + mCurDisableStencil = disableStencil; + + mDepthStencilStateIsDirty = false; + + return gl::NoError(); +} + +gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState. + if (!mRasterizerStateIsDirty && rasterState.pointDrawMode == mCurRasterState.pointDrawMode && + rasterState.multiSample == mCurRasterState.multiSample) + { + return gl::NoError(); + } + + 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->getStateCache().getRasterizerState( + modifiedRasterState, mCurScissorEnabled, &dxRasterState)); + } + else + { + ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled, + &dxRasterState)); + } + + mRenderer->getDeviceContext()->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + mRasterizerStateIsDirty = false; + + return gl::NoError(); +} + +void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (!mScissorStateIsDirty) + return; + + int modifiedScissorY = scissor.y; + if (mCurPresentPathFastEnabled) + { + modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y; + } + + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, modifiedScissorY); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = modifiedScissorY + std::max(0, scissor.height); + + mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect); + } + + mCurScissorRect = scissor; + mCurScissorEnabled = enabled; + mScissorStateIsDirty = false; +} + +void StateManager11::setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar) +{ + if (!mViewportStateIsDirty) + return; + + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth); + int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight); + int dxMinViewportBoundsX = -dxMaxViewportBoundsX; + int dxMinViewportBoundsY = -dxMaxViewportBoundsY; + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. + dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width); + dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height); + dxMinViewportBoundsX = 0; + dxMinViewportBoundsY = 0; + } + + int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); + int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); + int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT dxViewport; + 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); + } + + dxViewport.Width = static_cast<float>(dxViewportWidth); + dxViewport.Height = static_cast<float>(dxViewportHeight); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport); + + mCurViewport = viewport; + 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 (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) + + 2 * (viewport.x - dxViewportTopLeftX)) / + dxViewport.Width; + mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) + + 2 * (viewport.y - dxViewportTopLeftY)) / + dxViewport.Height; + mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width; + mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height; + } + + mPixelConstants.viewCoords[0] = viewport.width * 0.5f; + mPixelConstants.viewCoords[1] = viewport.height * 0.5f; + mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f); + mPixelConstants.viewCoords[3] = viewport.y + (viewport.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; + + mPixelConstants.viewScale[0] = 1.0f; + mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f; + mPixelConstants.viewScale[2] = 1.0f; + mPixelConstants.viewScale[3] = 1.0f; + + mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0]; + mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1]; + mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2]; + mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3]; + + mViewportStateIsDirty = false; +} + +void StateManager11::invalidateRenderTarget() +{ + mRenderTargetIsDirty = true; +} + +void StateManager11::invalidateBoundViews() +{ + mCurVertexSRVs.clear(); + mCurPixelSRVs.clear(); + + invalidateRenderTarget(); +} + +void StateManager11::invalidateEverything() +{ + mBlendStateIsDirty = true; + mDepthStencilStateIsDirty = true; + mRasterizerStateIsDirty = true; + mScissorStateIsDirty = true; + mViewportStateIsDirty = true; + + // We reset the current SRV data because it might not be in sync with D3D's state + // anymore. For example when a currently used SRV is used as an RTV, D3D silently + // remove it from its state. + invalidateBoundViews(); +} + +void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget, + ID3D11DepthStencilView *depthStencil) +{ + mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil); + mRenderTargetIsDirty = true; +} + +void StateManager11::setOneTimeRenderTargets( + const std::vector<ID3D11RenderTargetView *> &renderTargets, + ID3D11DepthStencilView *depthStencil) +{ + UINT count = static_cast<UINT>(renderTargets.size()); + auto renderTargetPointer = (!renderTargets.empty() ? renderTargets.data() : nullptr); + + mRenderer->getDeviceContext()->OMSetRenderTargets(count, renderTargetPointer, depthStencil); + mRenderTargetIsDirty = true; +} + +void StateManager11::onBeginQuery(Query11 *query) +{ + mCurrentQueries.insert(query); +} + +void StateManager11::onDeleteQueryObject(Query11 *query) +{ + mCurrentQueries.erase(query); +} + +gl::Error StateManager11::onMakeCurrent(const gl::ContextState &data) +{ + const gl::State &state = data.getState(); + + for (Query11 *query : mCurrentQueries) + { + query->pause(); + } + mCurrentQueries.clear(); + + for (GLenum queryType : QueryTypes) + { + gl::Query *query = state.getActiveQuery(queryType); + if (query != nullptr) + { + Query11 *query11 = GetImplAs<Query11>(query); + query11->resume(); + mCurrentQueries.insert(query11); + } + } + + return gl::NoError(); +} + +void StateManager11::setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + ID3D11ShaderResourceView *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)) + { + auto deviceContext = mRenderer->getDeviceContext(); + if (shaderType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(resourceSlot, 1, &srv); + } + else + { + deviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + } + + currentSRVs.update(resourceSlot, srv); + } +} + +gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, + size_t rangeStart, + size_t rangeEnd) +{ + if (rangeStart == rangeEnd) + { + return gl::NoError(); + } + + auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + gl::Range<size_t> clearRange(rangeStart, rangeStart); + clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed())); + + if (clearRange.empty()) + { + return gl::NoError(); + } + + auto deviceContext = mRenderer->getDeviceContext(); + if (samplerType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart), + static_cast<unsigned int>(rangeEnd - rangeStart), + &mNullSRVs[0]); + } + else + { + deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart), + static_cast<unsigned int>(rangeEnd - rangeStart), + &mNullSRVs[0]); + } + + for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex) + { + currentSRVs.update(samplerIndex, nullptr); + } + + return gl::NoError(); +} + +void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, + uintptr_t 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); + } + } +} + +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); + } +} + +void StateManager11::initialize(const gl::Caps &caps) +{ + mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits); + mCurPixelSRVs.initialize(caps.maxTextureImageUnits); + + // Initialize cached NULL SRV block + mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); + + mCurrentValueAttribs.resize(caps.maxVertexAttributes); +} + +void StateManager11::deinitialize() +{ + mCurrentValueAttribs.clear(); +} + +gl::Error StateManager11::syncFramebuffer(gl::Framebuffer *framebuffer) +{ + Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); + ANGLE_TRY(framebuffer11->markAttachmentsDirty()); + + if (framebuffer11->hasAnyInternalDirtyBit()) + { + ASSERT(framebuffer->id() != 0); + framebuffer11->syncInternalState(); + } + + if (!mRenderTargetIsDirty) + { + return gl::NoError(); + } + + mRenderTargetIsDirty = false; + + // 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(); + } + } + + // Get the color render buffer and serial + // Also extract the render target dimensions and view + unsigned int renderTargetWidth = 0; + unsigned int renderTargetHeight = 0; + RTVArray framebufferRTVs; + bool missingColorRenderTarget = true; + + framebufferRTVs.fill(nullptr); + + const auto &colorRTs = framebuffer11->getCachedColorRenderTargets(); + + size_t appliedRTIndex = 0; + bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; + const auto &drawStates = framebuffer->getDrawBufferStates(); + + 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)) + { + continue; + } + + if (renderTarget) + { + framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView(); + ASSERT(framebufferRTVs[appliedRTIndex]); + + if (missingColorRenderTarget) + { + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + missingColorRenderTarget = false; + } + } + + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getColorbuffer(rtIndex); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, renderTarget->getTexture()); + + appliedRTIndex++; + } + + // Get the depth stencil buffers + ID3D11DepthStencilView *framebufferDSV = nullptr; + const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); + if (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(); + } + + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getDepthOrStencilbuffer(); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, depthStencilRenderTarget->getTexture()); + } + + // TODO(jmadill): Use context caps? + UINT drawBuffers = mRenderer->getNativeCaps().maxDrawBuffers; + + // Apply the render target and depth stencil + mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, framebufferRTVs.data(), + framebufferDSV); + + // The D3D11 blend state is heavily dependent on the current render target. + mBlendStateIsDirty = true; + + setViewportBounds(renderTargetWidth, renderTargetHeight); + + return gl::NoError(); +} + +gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state, + VertexDataManager *vertexDataManager) +{ + const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask(); + const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); + const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + + for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs)) + { + if (vertexAttributes[attribIndex].enabled) + continue; + + mDirtyCurrentValueAttribs.reset(attribIndex); + + const auto ¤tValue = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); + auto currentValueAttrib = &mCurrentValueAttribs[attribIndex]; + currentValueAttrib->currentValueType = currentValue.Type; + currentValueAttrib->attribute = &vertexAttributes[attribIndex]; + + ANGLE_TRY(vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib, + static_cast<size_t>(attribIndex))); + } + + return gl::NoError(); +} + +const std::vector<TranslatedAttribute> &StateManager11::getCurrentValueAttribs() const +{ + return mCurrentValueAttribs; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h new file mode 100755 index 000000000..771eb439f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -0,0 +1,202 @@ +// +// 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.h: Defines a class for caching D3D11 state + +#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ +#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ + +#include <array> + +#include "libANGLE/angletypes.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +struct RenderTargetDesc; +struct Renderer11DeviceCaps; + +struct dx_VertexConstants11 +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; + float viewScale[4]; +}; + +struct dx_PixelConstants11 +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; + float viewScale[4]; +}; + +class StateManager11 final : angle::NonCopyable +{ + public: + StateManager11(Renderer11 *renderer); + ~StateManager11(); + + void initialize(const gl::Caps &caps); + void deinitialize(); + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + + gl::Error setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask); + + gl::Error setDepthStencilState(const gl::State &glState); + + gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + + void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar); + + void updatePresentPath(bool presentPathFastActive, + const gl::FramebufferAttachment *framebufferAttachment); + + const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; } + const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; } + + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + void setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + ID3D11ShaderResourceView *srv); + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd); + + gl::Error syncFramebuffer(gl::Framebuffer *framebuffer); + + void invalidateRenderTarget(); + void invalidateBoundViews(); + void invalidateEverything(); + + void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget, + ID3D11DepthStencilView *depthStencil); + void setOneTimeRenderTargets(const std::vector<ID3D11RenderTargetView *> &renderTargets, + ID3D11DepthStencilView *depthStencil); + + void onBeginQuery(Query11 *query); + void onDeleteQueryObject(Query11 *query); + gl::Error onMakeCurrent(const gl::ContextState &data); + + gl::Error updateCurrentValueAttribs(const gl::State &state, + VertexDataManager *vertexDataManager); + + const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const; + + private: + void setViewportBounds(const int width, const int height); + void unsetConflictingSRVs(gl::SamplerType shaderType, + uintptr_t resource, + const gl::ImageIndex &index); + void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment, + ID3D11Resource *resource); + + Renderer11 *mRenderer; + + // Blend State + bool mBlendStateIsDirty; + // TODO(dianx) temporary representation of a dirty bit. once we move enough states in, + // try experimenting with dirty bit instead of a bool + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied depth stencil state + bool mDepthStencilStateIsDirty; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + unsigned int mCurStencilSize; + Optional<bool> mCurDisableDepth; + Optional<bool> mCurDisableStencil; + + // Currently applied rasterizer state + bool mRasterizerStateIsDirty; + gl::RasterizerState mCurRasterState; + + // Currently applied scissor rectangle state + bool mScissorStateIsDirty; + bool mCurScissorEnabled; + gl::Rectangle mCurScissorRect; + + // Currently applied viewport state + bool mViewportStateIsDirty; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Things needed in viewport state + dx_VertexConstants11 mVertexConstants; + dx_PixelConstants11 mPixelConstants; + + // Render target variables + gl::Extents mViewportBounds; + + // EGL_ANGLE_experimental_present_path variables + bool mCurPresentPathFastEnabled; + int mCurPresentPathFastColorBufferHeight; + + // Current RenderTarget state + bool mRenderTargetIsDirty; + + // Queries that are currently active in this state + std::set<Query11 *> mCurrentQueries; + + // Currently applied textures + struct SRVRecord + { + uintptr_t srv; + uintptr_t resource; + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + }; + + // A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV + // We might want to investigate a more robust approach that is also fast when there's + // a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will + // waste time on SRVs 1-6.) + class SRVCache : angle::NonCopyable + { + public: + SRVCache() : mHighestUsedSRV(0) {} + + void initialize(size_t size) { mCurrentSRVs.resize(size); } + + size_t size() const { return mCurrentSRVs.size(); } + size_t highestUsed() const { return mHighestUsedSRV; } + + const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; } + void clear(); + void update(size_t resourceIndex, ID3D11ShaderResourceView *srv); + + private: + std::vector<SRVRecord> mCurrentSRVs; + size_t mHighestUsedSRV; + }; + + SRVCache mCurVertexSRVs; + SRVCache mCurPixelSRVs; + + // A block of NULL pointers, cached so we don't re-allocate every draw call + std::vector<ID3D11ShaderResourceView *> mNullSRVs; + + // Current translations of "Current-Value" data - owned by Context, not VertexArray. + gl::AttributesMask mDirtyCurrentValueAttribs; + std::vector<TranslatedAttribute> mCurrentValueAttribs; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp new file mode 100755 index 000000000..fbbdf552a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp @@ -0,0 +1,102 @@ +// +// Copyright (c) 2016 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. +// + +// StreamProducerNV12.cpp: Implements the stream producer for NV12 textures + +#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h" + +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer) + : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0) +{ +} + +StreamProducerNV12::~StreamProducerNV12() +{ + SafeRelease(mTexture); +} + +egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const +{ + ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer); + + // Check that the texture originated from our device + ID3D11Device *device; + textureD3D->GetDevice(&device); + if (device != mRenderer->getDevice()) + { + return egl::Error(EGL_BAD_PARAMETER, "Texture not created on ANGLE D3D device"); + } + + // Get the description and validate it + D3D11_TEXTURE2D_DESC desc; + textureD3D->GetDesc(&desc); + if (desc.Format != DXGI_FORMAT_NV12) + { + return egl::Error(EGL_BAD_PARAMETER, "Texture format not DXGI_FORMAT_NV12"); + } + if (desc.Width < 1 || desc.Height < 1) + { + return egl::Error(EGL_BAD_PARAMETER, "Texture is of size 0"); + } + if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0) + { + return egl::Error(EGL_BAD_PARAMETER, "Texture dimensions are not even"); + } + return egl::Error(EGL_SUCCESS); +} + +void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) +{ + ASSERT(pointer != nullptr); + ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer); + + // Check that the texture originated from our device + ID3D11Device *device; + textureD3D->GetDevice(&device); + + // Get the description + D3D11_TEXTURE2D_DESC desc; + textureD3D->GetDesc(&desc); + + // Release the previous texture if there is one + SafeRelease(mTexture); + + mTexture = textureD3D; + mTexture->AddRef(); + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0)); +} + +egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex) +{ + // The UV plane of NV12 textures has half the width/height of the Y plane + egl::Stream::GLTextureDescription desc; + desc.width = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2); + desc.height = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2); + desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8; + desc.mipLevels = 0; + return desc; +} + +ID3D11Texture2D *StreamProducerNV12::getD3DTexture() +{ + return mTexture; +} + +UINT StreamProducerNV12::getArraySlice() +{ + return mArraySlice; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h new file mode 100755 index 000000000..304c9dfe5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2016 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. +// + +// StreamProducerNV12.h: Interface for a NV12 texture stream producer + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_ + +#include "libANGLE/renderer/StreamProducerImpl.h" + +namespace rx +{ +class Renderer11; + +class StreamProducerNV12 : public StreamProducerImpl +{ + public: + StreamProducerNV12(Renderer11 *renderer); + ~StreamProducerNV12() override; + + egl::Error validateD3DNV12Texture(void *pointer) const override; + void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) override; + egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) override; + + // Gets a pointer to the internal D3D texture + ID3D11Texture2D *getD3DTexture(); + + // Gets the slice index for the D3D texture that the frame is in + UINT getArraySlice(); + + private: + Renderer11 *mRenderer; + + ID3D11Texture2D *mTexture; + UINT mArraySlice; + UINT mTextureWidth; + UINT mTextureHeight; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp new file mode 100755 index 000000000..a410c425d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -0,0 +1,867 @@ +// +// 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. +// + +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. + +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" + +#include <EGL/eglext.h> + +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "third_party/trace_event/trace_event.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" + +#ifdef ANGLE_ENABLE_KEYEDMUTEX +#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX +#else +#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED +#endif + +namespace rx +{ + +namespace +{ +bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *nativeWindow, EGLint orientation) +{ + // We don't need an offscreen texture if either orientation = INVERT_Y, + // or present path fast is enabled and we're not rendering onto an offscreen surface. + return orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && + !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow()); +} +} // anonymous namespace + +SwapChain11::SwapChain11(Renderer11 *renderer, + NativeWindow11 *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) + : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat), + mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mOrientation(orientation), + mAppCreatedShareHandle(mShareHandle != nullptr), + mSwapInterval(0), + mPassThroughResourcesInit(false), + mNativeWindow(nativeWindow), + mFirstSwap(true), + mSwapChain(nullptr), + mSwapChain1(nullptr), + mKeyedMutex(nullptr), + mBackBufferTexture(nullptr), + mBackBufferRTView(nullptr), + mBackBufferSRView(nullptr), + mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)), + mOffscreenTexture(nullptr), + mOffscreenRTView(nullptr), + mOffscreenSRView(nullptr), + mDepthStencilTexture(nullptr), + mDepthStencilDSView(nullptr), + mDepthStencilSRView(nullptr), + mQuadVB(nullptr), + mPassThroughSampler(nullptr), + mPassThroughIL(nullptr), + mPassThroughVS(nullptr), + mPassThroughPS(nullptr), + mPassThroughRS(nullptr), + mColorRenderTarget(this, renderer, false), + mDepthStencilRenderTarget(this, renderer, true) +{ + // Sanity check that if present path fast is active then we're using the default orientation + ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0); +} + +SwapChain11::~SwapChain11() +{ + release(); +} + +void SwapChain11::release() +{ + SafeRelease(mSwapChain1); + SafeRelease(mSwapChain); + SafeRelease(mKeyedMutex); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); + SafeRelease(mQuadVB); + SafeRelease(mPassThroughSampler); + SafeRelease(mPassThroughIL); + SafeRelease(mPassThroughVS); + SafeRelease(mPassThroughPS); + SafeRelease(mPassThroughRS); + + if (!mAppCreatedShareHandle) + { + mShareHandle = NULL; + } +} + +void SwapChain11::releaseOffscreenColorBuffer() +{ + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); +} + +void SwapChain11::releaseOffscreenDepthBuffer() +{ + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); +} + +EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight) +{ + if (mNeedsOffscreenTexture) + { + EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) +{ + ASSERT(mNeedsOffscreenTexture); + + TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // D3D11 does not allow zero size textures + ASSERT(backbufferWidth >= 1); + ASSERT(backbufferHeight >= 1); + + // Preserve the render target content + ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; + if (previousOffscreenTexture) + { + previousOffscreenTexture->AddRef(); + } + const int previousWidth = mWidth; + const int previousHeight = mHeight; + + releaseOffscreenColorBuffer(); + + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + + // If the app passed in a share handle or D3D texture, open the resource + // See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer + if (mAppCreatedShareHandle || mD3DTexture != nullptr) + { + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + ASSERT(SUCCEEDED(result)); + + mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11); + SafeRelease(tempResource11); + } + else if (mD3DTexture != nullptr) + { + mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture); + } + else + { + UNREACHABLE(); + } + ASSERT(mOffscreenTexture != nullptr); + } + else + { + const bool useSharedResource = + !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; + offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Quality = 0; + offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; + offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + offscreenTextureDesc.CPUAccessFlags = 0; + offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0; + + HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); + + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client + if (useSharedResource) + { + IDXGIResource *offscreenTextureResource = NULL; + result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); + + // Fall back to no share handle on failure + if (FAILED(result)) + { + ERR("Could not query offscreen texture resource: %08lX", result); + } + else + { + result = offscreenTextureResource->GetSharedHandle(&mShareHandle); + SafeRelease(offscreenTextureResource); + + if (FAILED(result)) + { + mShareHandle = NULL; + ERR("Could not get offscreen texture shared handle: %08lX", result); + } + } + } + } + + // This may return null if the original texture was created without a keyed mutex. + mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture); + + D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; + offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Texture2D.MipSlice = 0; + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); + + result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); + + if (previousOffscreenTexture != nullptr) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, backbufferWidth); + sourceBox.top = std::max(previousHeight - backbufferHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(backbufferHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, + previousOffscreenTexture, 0, &sourceBox); + + SafeRelease(previousOffscreenTexture); + + if (mSwapChain) + { + swapRect(0, 0, backbufferWidth, backbufferHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight) +{ + releaseOffscreenDepthBuffer(); + + if (mDepthBufferFormat != GL_NONE) + { + const d3d11::Format &depthBufferFormatInfo = + d3d11::Format::Get(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; + depthStencilTextureDesc.SampleDesc.Count = 1; + depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + + depthStencilTextureDesc.CPUAccessFlags = 0; + depthStencilTextureDesc.MiscFlags = 0; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = + device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); + if (FAILED(result)) + { + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); + + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; + depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Flags = 0; + depthStencilDesc.Texture2D.MipSlice = 0; + + result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; + depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; + depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); + + result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +{ + TRACE_EVENT0("gpu.angle", "SwapChain11::resize"); + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + return EGL_SUCCESS; + } + + // Don't resize unnecessarily + if (mWidth == backbufferWidth && mHeight == backbufferHeight) + { + return EGL_SUCCESS; + } + + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); + + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); + + // Resize swap chain + DXGI_SWAP_CHAIN_DESC desc; + HRESULT result = mSwapChain->GetDesc(&desc); + if (FAILED(result)) + { + ERR("Error reading swap chain description: 0x%08X", result); + release(); + return EGL_BAD_ALLOC; + } + + result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, getSwapChainNativeFormat(), 0); + + if (FAILED(result)) + { + ERR("Error resizing swap chain buffers: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource"); + } + } + + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); +} + +DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const +{ + // Return a render target format for offscreen rendering is supported by IDXGISwapChain. + // MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx + return (mOffscreenRenderTargetFormat == GL_BGRA8_EXT) ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM; +} + +EGLint SwapChain11::reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) +{ + mSwapInterval = static_cast<unsigned int>(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] + // range + return EGL_BAD_PARAMETER; + } + + // If the swap chain already exists, just resize + if (mSwapChain != nullptr) + { + return resize(backbufferWidth, backbufferHeight); + } + + TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain1); + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + releaseOffscreenColorBuffer(); + return EGL_SUCCESS; + } + + if (mNativeWindow->getNativeWindow()) + { + HRESULT result = mNativeWindow->createSwapChain(device, mRenderer->getDxgiFactory(), + getSwapChainNativeFormat(), backbufferWidth, + backbufferHeight, &mSwapChain); + + if (FAILED(result)) + { + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) + { + mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); + } + + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); +} + +void SwapChain11::initPassThroughResources() +{ + if (mPassThroughResourcesInit) + { + return; + } + + TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // Make sure our resources are all not allocated, when we create + ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); + ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + + result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); + + // Use the default rasterizer state but without culling + D3D11_RASTERIZER_DESC rasterizerDesc; + rasterizerDesc.FillMode = D3D11_FILL_SOLID; + rasterizerDesc.CullMode = D3D11_CULL_NONE; + rasterizerDesc.FrontCounterClockwise = FALSE; + rasterizerDesc.DepthBias = 0; + rasterizerDesc.SlopeScaledDepthBias = 0.0f; + rasterizerDesc.DepthBiasClamp = 0.0f; + rasterizerDesc.DepthClipEnable = TRUE; + rasterizerDesc.ScissorEnable = FALSE; + rasterizerDesc.MultisampleEnable = FALSE; + rasterizerDesc.AntialiasedLineEnable = FALSE; + result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state"); + + mPassThroughResourcesInit = true; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (mNeedsOffscreenTexture) + { + EGLint result = copyOffscreenToBackbuffer(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = present(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + + mRenderer->onSwap(); + + return EGL_SUCCESS; +} + +EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + initPassThroughResources(); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return EGL_BAD_ACCESS; + } + + d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + // Invert the quad vertices depending on the surface orientation. + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) + { + std::swap(x1, x2); + } + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0) + { + std::swap(y1, y2); + } + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); + + deviceContext->Unmap(mQuadVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); + + // Apply state + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + + deviceContext->RSSetState(mPassThroughRS); + + // Apply shaders + deviceContext->IASetInputLayout(mPassThroughIL); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + deviceContext->VSSetShader(mPassThroughVS, NULL, 0); + deviceContext->PSSetShader(mPassThroughPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + auto stateManager = mRenderer->getStateManager(); + + // Apply render targets + stateManager->setOneTimeRenderTarget(mBackBufferRTView, nullptr); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(mWidth); + viewport.Height = static_cast<FLOAT>(mHeight); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + + // Draw + deviceContext->Draw(4, 0); + + // Rendering to the swapchain is now complete. Now we can call Present(). + // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the + // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one. + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + UINT swapInterval = mSwapInterval; +#if ANGLE_VSYNC == ANGLE_DISABLED + swapInterval = 0; +#endif + + HRESULT result = S_OK; + + // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. + if (mSwapChain1 != nullptr) + { + if (mFirstSwap) + { + // Can't swap with a dirty rect if this swap chain has never swapped before + DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } + else + { + RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), + static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)}; + DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } + } + else + { + result = mSwapChain->Present(swapInterval, 0); + } + + mFirstSwap = false; + + // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render + // target. Mark it dirty. + mRenderer->getStateManager()->invalidateRenderTarget(); + + if (result == DXGI_ERROR_DEVICE_REMOVED) + { + ERR("Present failed: the D3D11 device was removed: 0x%08X", + mRenderer->getDevice()->GetDeviceRemovedReason()); + return EGL_CONTEXT_LOST; + } + else if (result == DXGI_ERROR_DEVICE_RESET) + { + ERR("Present failed: the D3D11 device was reset from a bad command."); + return EGL_CONTEXT_LOST; + } + else if (FAILED(result)) + { + ERR("Present failed with error code 0x%08X", result); + } + + mNativeWindow->commitChange(); + + return EGL_SUCCESS; +} + +ID3D11Texture2D *SwapChain11::getOffscreenTexture() +{ + return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture; +} + +ID3D11RenderTargetView *SwapChain11::getRenderTarget() +{ + return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView; +} + +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +{ + return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView; +} + +ID3D11DepthStencilView *SwapChain11::getDepthStencil() +{ + return mDepthStencilDSView; +} + +ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() +{ + return mDepthStencilSRView; +} + +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ + return mDepthStencilTexture; +} + +void SwapChain11::recreate() +{ + // possibly should use this method instead of reset +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h new file mode 100755 index 000000000..1d7e57b7c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2012 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. +// + +// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ + +#include "common/angleutils.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" + +namespace rx +{ +class Renderer11; +class NativeWindow11; + +class SwapChain11 final : public SwapChainD3D +{ + public: + SwapChain11(Renderer11 *renderer, + NativeWindow11 *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); + virtual ~SwapChain11(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) override; + EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) override; + void recreate() override; + + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + + ID3D11Texture2D *getOffscreenTexture(); + ID3D11RenderTargetView *getRenderTarget(); + ID3D11ShaderResourceView *getRenderTargetShaderResource(); + + ID3D11Texture2D *getDepthStencilTexture(); + ID3D11DepthStencilView *getDepthStencil(); + ID3D11ShaderResourceView *getDepthStencilShaderResource(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + void *getKeyedMutex() override { return mKeyedMutex; } + + private: + void release(); + void initPassThroughResources(); + + void releaseOffscreenColorBuffer(); + void releaseOffscreenDepthBuffer(); + EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight); + + DXGI_FORMAT getSwapChainNativeFormat() const; + + EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height); + EGLint present(EGLint x, EGLint y, EGLint width, EGLint height); + + Renderer11 *mRenderer; + EGLint mWidth; + EGLint mHeight; + const EGLint mOrientation; + bool mAppCreatedShareHandle; + unsigned int mSwapInterval; + bool mPassThroughResourcesInit; + + NativeWindow11 *mNativeWindow; // Handler for the Window that the surface is created for. + + bool mFirstSwap; + IDXGISwapChain *mSwapChain; + IDXGISwapChain1 *mSwapChain1; + IDXGIKeyedMutex *mKeyedMutex; + + ID3D11Texture2D *mBackBufferTexture; + ID3D11RenderTargetView *mBackBufferRTView; + ID3D11ShaderResourceView *mBackBufferSRView; + + const bool mNeedsOffscreenTexture; + ID3D11Texture2D *mOffscreenTexture; + ID3D11RenderTargetView *mOffscreenRTView; + ID3D11ShaderResourceView *mOffscreenSRView; + + ID3D11Texture2D *mDepthStencilTexture; + ID3D11DepthStencilView *mDepthStencilDSView; + ID3D11ShaderResourceView *mDepthStencilSRView; + + ID3D11Buffer *mQuadVB; + ID3D11SamplerState *mPassThroughSampler; + ID3D11InputLayout *mPassThroughIL; + ID3D11VertexShader *mPassThroughVS; + ID3D11PixelShader *mPassThroughPS; + ID3D11RasterizerState *mPassThroughRS; + + SurfaceRenderTarget11 mColorRenderTarget; + SurfaceRenderTarget11 mDepthStencilRenderTarget; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp new file mode 100755 index 000000000..36c888dd3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -0,0 +1,3390 @@ +// +// 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. +// + +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 +// texture. + +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" + +#include <tuple> + +#include "common/MemoryBuffer.h" +#include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" + +namespace rx +{ + +TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil) + : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil) +{ +} + +bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const +{ + return std::tie(baseLevel, mipLevels, swizzle, dropStencil) < + std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil); +} + +TextureStorage11::TextureStorage11(Renderer11 *renderer, + UINT bindFlags, + UINT miscFlags, + GLenum internalFormat) + : mRenderer(renderer), + mTopLevel(0), + mMipLevels(0), + mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())), + mTextureWidth(0), + mTextureHeight(0), + mTextureDepth(0), + mDropStencilTexture(nullptr), + mBindFlags(bindFlags), + mMiscFlags(miscFlags) +{ + mLevelSRVs.fill(nullptr); + mLevelBlitSRVs.fill(nullptr); +} + +TextureStorage11::~TextureStorage11() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mLevelSRVs[level]); + SafeRelease(mLevelBlitSRVs[level]); + } + + for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) + { + SafeRelease(i->second); + } + mSrvCache.clear(); + SafeRelease(mDropStencilTexture); +} + +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget) +{ + UINT bindFlags = 0; + + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + + return bindFlags; +} + +DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget, + int levels) +{ + UINT miscFlags = 0; + + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + if (renderTarget && levels > 1) + { + if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel)) + { + miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + } + } + + return miscFlags; +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +UINT TextureStorage11::getMiscFlags() const +{ + return mMiscFlags; +} + +int TextureStorage11::getTopLevel() const +{ + // Applying top level is meant to be encapsulated inside TextureStorage11. + UNREACHABLE(); + return mTopLevel; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +bool TextureStorage11::supportsNativeMipmapFunction() const +{ + return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0; +} + +int TextureStorage11::getLevelCount() const +{ + return mMipLevels - mTopLevel; +} + +int TextureStorage11::getLevelWidth(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1); +} + +int TextureStorage11::getLevelHeight(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1); +} + +int TextureStorage11::getLevelDepth(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1); +} + +UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const +{ + UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits<UINT>::max()); + return subresource; +} + +gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) +{ + // Make sure to add the level offset for our tiny compressed texture workaround + const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel(); + bool swizzleRequired = textureState.swizzleRequired(); + bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState()); + unsigned int mipLevels = + mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, + // which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel); + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(!swizzleRequired); + ASSERT(mipLevels == 1 || mipLevels == mMipLevels); + } + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // We must ensure that the level zero texture is in sync with mipped texture. + ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1)); + } + + if (swizzleRequired) + { + verifySwizzleExists(textureState.getSwizzleState()); + } + + // We drop the stencil when sampling from the SRV if three conditions hold: + // 1. the drop stencil workaround is enabled. + bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures; + // 2. this is a stencil texture. + bool hasStencil = (mFormatInfo.format().stencilBits > 0); + // 3. the texture has a 1x1 or 2x2 mip. + bool hasSmallMips = (getLevelWidth(mMipLevels - 1) <= 2 || getLevelHeight(mMipLevels - 1) <= 2); + + bool useDropStencil = (workaround && hasStencil && hasSmallMips); + if (useDropStencil) + { + // Ensure drop texture gets re-created, if SRV is cached. + ANGLE_TRY(createDropStencilTexture()); + } + + SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil); + ANGLE_TRY(getCachedOrCreateSRV(key, outSRV)); + + return gl::NoError(); +} + +gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key, + ID3D11ShaderResourceView **outSRV) +{ + auto iter = mSrvCache.find(key); + if (iter != mSrvCache.end()) + { + *outSRV = iter->second; + return gl::NoError(); + } + + ID3D11Resource *texture = nullptr; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + + if (key.swizzle) + { + const auto &swizzleFormat = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); + ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0); + ANGLE_TRY(getSwizzleTexture(&texture)); + format = swizzleFormat.srvFormat; + } + else if (key.dropStencil) + { + ASSERT(mDropStencilTexture); + texture = mDropStencilTexture; + format = DXGI_FORMAT_R32_FLOAT; + } + else + { + ANGLE_TRY(getResource(&texture)); + format = mFormatInfo.srvFormat; + } + + ID3D11ShaderResourceView *srv = nullptr; + + ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv)); + + mSrvCache.insert(std::make_pair(key, srv)); + *outSRV = srv; + + return gl::NoError(); +} + +gl::Error TextureStorage11::getSRVLevel(int mipLevel, + bool blitSRV, + ID3D11ShaderResourceView **outSRV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs; + auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs; + + if (!levelSRVs[mipLevel]) + { + // Only create a different SRV for blit if blit format is different from regular srv format + if (otherLevelSRVs[mipLevel] && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat) + { + levelSRVs[mipLevel] = otherLevelSRVs[mipLevel]; + levelSRVs[mipLevel]->AddRef(); + } + else + { + ID3D11Resource *resource = nullptr; + ANGLE_TRY(getResource(&resource)); + + DXGI_FORMAT resourceFormat = + blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat; + ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel])); + } + } + + *outSRV = levelSRVs[mipLevel]; + + return gl::NoError(); +} + +gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, + GLint maxLevel, + ID3D11ShaderResourceView **outSRV) +{ + unsigned int mipLevels = maxLevel - baseLevel + 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, + // which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel); + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(mipLevels == 1 || mipLevels == mMipLevels); + } + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // We must ensure that the level zero texture is in sync with mipped texture. + ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1)); + } + + // TODO(jmadill): Assert we don't need to drop stencil. + + SRVKey key(baseLevel, mipLevels, false, false); + ANGLE_TRY(getCachedOrCreateSRV(key, outSRV)); + + return gl::NoError(); +} + +const d3d11::Format &TextureStorage11::getFormatSet() const +{ + return mFormatInfo; +} + +gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarget) +{ + for (int level = 0; level < getLevelCount(); level++) + { + // Check if the swizzle for this level is out of date + if (mSwizzleCache[level] != swizzleTarget) + { + // Need to re-render the swizzle for this level + ID3D11ShaderResourceView *sourceSRV = nullptr; + ANGLE_TRY(getSRVLevel(level, true, &sourceSRV)); + + ID3D11RenderTargetView *destRTV = nullptr; + ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV)); + + gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + Blit11 *blitter = mRenderer->getBlitter(); + + ANGLE_TRY(blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget)); + + mSwizzleCache[level] = swizzleTarget; + } + } + + return gl::NoError(); +} + +void TextureStorage11::markLevelDirty(int mipLevel) +{ + if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache)) + { + // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is + // not a valid swizzle combination + mSwizzleCache[mipLevel] = gl::SwizzleState(); + } + + SafeRelease(mDropStencilTexture); +} + +void TextureStorage11::markDirty() +{ + for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + { + markLevelDirty(mipLevel); + } +} + +gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, + unsigned int sourceSubresource, + const gl::ImageIndex &index, + const gl::Box ©Area) +{ + ASSERT(srcTexture); + + const GLint level = index.mipIndex; + + markLevelDirty(level); + + gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 && + copyArea.width == texSize.width && copyArea.height == texSize.height && + copyArea.depth == texSize.depth; + + ID3D11Resource *dstTexture = nullptr; + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we + // should update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ANGLE_TRY(getMippedResource(&dstTexture)); + } + else + { + ANGLE_TRY(getResource(&dstTexture)); + } + + unsigned int dstSubresource = getSubresourceIndex(index); + + ASSERT(dstTexture); + + const d3d11::DXGIFormatSize &dxgiFormatSizeInfo = + d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat); + if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) + { + // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead + Blit11 *blitter = mRenderer->getBlitter(); + TextureHelper11 source = TextureHelper11::MakeAndReference(srcTexture, getFormatSet()); + TextureHelper11 dest = TextureHelper11::MakeAndReference(dstTexture, getFormatSet()); + return blitter->copyDepthStencil(source, sourceSubresource, copyArea, texSize, dest, + dstSubresource, copyArea, texSize, nullptr); + } + + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = + copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth); + srcBox.bottom = + copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, + srcTexture, sourceSubresource, fullCopy ? nullptr : &srcBox); + return gl::NoError(); +} + +gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture, + unsigned int dstSubresource, + const gl::ImageIndex &index, + const gl::Box ®ion) +{ + ASSERT(dstTexture); + + ID3D11Resource *srcTexture = nullptr; + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we + // should update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ANGLE_TRY(getMippedResource(&srcTexture)); + } + else + { + ANGLE_TRY(getResource(&srcTexture)); + } + + ASSERT(srcTexture); + + unsigned int srcSubresource = getSubresourceIndex(index); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox + // should be nullptr. + D3D11_BOX srcBox; + D3D11_BOX *pSrcBox = nullptr; + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the + // source box is specified. This is okay, since we don't perform CopySubresourceRegion on + // depth/stencil textures on 9_3. + ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN); + srcBox.left = region.x; + srcBox.right = region.x + region.width; + srcBox.top = region.y; + srcBox.bottom = region.y + region.height; + srcBox.front = region.z; + srcBox.back = region.z + region.depth; + pSrcBox = &srcBox; + } + + context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, + srcTexture, srcSubresource, pSrcBox); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) +{ + ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); + + markLevelDirty(destIndex.mipIndex); + + RenderTargetD3D *source = nullptr; + ANGLE_TRY(getRenderTarget(sourceIndex, &source)); + + RenderTargetD3D *dest = nullptr; + ANGLE_TRY(getRenderTarget(destIndex, &dest)); + + ID3D11ShaderResourceView *sourceSRV = + GetAs<RenderTarget11>(source)->getBlitShaderResourceView(); + ID3D11RenderTargetView *destRTV = GetAs<RenderTarget11>(dest)->getRenderTargetView(); + + gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); + gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); + + gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); + gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); + + Blit11 *blitter = mRenderer->getBlitter(); + return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, + nullptr, + gl::GetInternalFormatInfo(source->getInternalFormat()).format, + GL_LINEAR, false, false, false); +} + +void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState) +{ + for (unsigned int level = 0; level < mMipLevels; level++) + { + ASSERT(mSwizzleCache[level] == swizzleState); + } +} + +void TextureStorage11::clearSRVCache() +{ + markDirty(); + + auto iter = mSrvCache.begin(); + while (iter != mSrvCache.end()) + { + if (!iter->first.swizzle) + { + SafeRelease(iter->second); + iter = mSrvCache.erase(iter); + } + else + { + iter++; + } + } + + for (size_t level = 0; level < mLevelSRVs.size(); level++) + { + SafeRelease(mLevelSRVs[level]); + SafeRelease(mLevelBlitSRVs[level]); + } +} + +gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + ID3D11Resource *sourceResouce = nullptr; + ANGLE_TRY(getResource(&sourceResouce)); + + TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage); + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + + dest11->markDirty(); + + return gl::NoError(); +} + +gl::Error TextureStorage11::setData(const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum inputType, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) +{ + ASSERT(!image->isDirty()); + + markLevelDirty(index.mipIndex); + + ID3D11Resource *resource = nullptr; + ANGLE_TRY(getResource(&resource)); + ASSERT(resource); + + UINT destSubresource = getSubresourceIndex(index); + + const auto sizedInputFormat = image->getSizedInputFormat(inputType); + const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat); + + gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), + getLevelDepth(index.mipIndex)); + bool fullUpdate = (destBox == nullptr || *destBox == levelBox); + ASSERT(inputFormat.depthBits == 0 || fullUpdate); + + // TODO(jmadill): Handle compressed formats + // Compressed formats have different load syntax, so we'll have to handle them with slightly + // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData + // with compressed formats in the calling logic. + ASSERT(!inputFormat.compressed); + + const int width = destBox ? destBox->width : static_cast<int>(image->getWidth()); + const int height = destBox ? destBox->height : static_cast<int>(image->getHeight()); + const int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth()); + GLuint srcRowPitch = 0; + ANGLE_TRY_RESULT( + inputFormat.computeRowPitch(width, unpack.alignment, unpack.rowLength), + srcRowPitch); + GLuint srcDepthPitch = 0; + ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(height, unpack.imageHeight, srcRowPitch), + srcDepthPitch); + GLuint srcSkipBytes = 0; + ANGLE_TRY_RESULT( + inputFormat.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()), + srcSkipBytes); + + const d3d11::Format &d3d11Format = + d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps()); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat); + + const size_t outputPixelSize = dxgiFormatInfo.pixelBytes; + + UINT bufferRowPitch = static_cast<unsigned int>(outputPixelSize) * width; + UINT bufferDepthPitch = bufferRowPitch * height; + + const size_t neededSize = bufferDepthPitch * depth; + MemoryBuffer *conversionBuffer = nullptr; + const uint8_t *data = nullptr; + + LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(inputType); + if (loadFunctionInfo.requiresConversion) + { + ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer)); + loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, + srcDepthPitch, conversionBuffer->data(), bufferRowPitch, + bufferDepthPitch); + data = conversionBuffer->data(); + } + else + { + data = pixelData + srcSkipBytes; + bufferRowPitch = srcRowPitch; + bufferDepthPitch = srcDepthPitch; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + if (!fullUpdate) + { + ASSERT(destBox); + + D3D11_BOX destD3DBox; + destD3DBox.left = destBox->x; + destD3DBox.right = destBox->x + destBox->width; + destD3DBox.top = destBox->y; + destD3DBox.bottom = destBox->y + destBox->height; + destD3DBox.front = destBox->z; + destD3DBox.back = destBox->z + destBox->depth; + + immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data, + bufferRowPitch, bufferDepthPitch); + } + else + { + immediateContext->UpdateSubresource(resource, destSubresource, nullptr, data, + bufferRowPitch, bufferDepthPitch); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11::createDropStencilTexture() +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Drop stencil texture not implemented."); +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + swapchain->getRenderTargetInternalFormat()), + mTexture(swapchain->getOffscreenTexture()), + mLevelZeroTexture(nullptr), + mLevelZeroRenderTarget(nullptr), + mUseLevelZeroTexture(false), + mSwizzleTexture(nullptr) +{ + mTexture->AddRef(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; + mSwizzleRenderTargets[i] = nullptr; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + mTextureDepth = 1; + mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat), + mTexture(nullptr), + mHasKeyedMutex(false), + mLevelZeroTexture(nullptr), + mLevelZeroRenderTarget(nullptr), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture(nullptr) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; + mSwizzleRenderTargets[i] = nullptr; + } + + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = 1; + + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != nullptr) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the + // TextureStorage. + gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage(); + if (error.isError()) + { + // TODO: Find a way to report this back to the context + ERR("Error initialization texture storage: %x", error.getCode()); + } + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + SafeRelease(mLevelZeroTexture); + SafeDelete(mLevelZeroRenderTarget); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mRenderTarget[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } + + if (mHasKeyedMutex) + { + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); + } +} + +gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage); + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture) + { + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + + return gl::NoError(); + } + + ID3D11Resource *sourceResouce = nullptr; + ANGLE_TRY(getResource(&sourceResouce)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + immediateContext->CopyResource(destResource, sourceResouce); + dest11->markDirty(); + + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + bool lastSetting = mUseLevelZeroTexture; + + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + ANGLE_TRY(ensureTextureExists(1)); + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, nullptr); + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, nullptr); + } + + mUseLevelZeroTexture = false; + } + + if (lastSetting != mUseLevelZeroTexture) + { + // Mark everything as dirty to be conservative. + if (mLevelZeroRenderTarget) + { + mLevelZeroRenderTarget->signalDirty(); + } + for (auto *renderTarget : mRenderTarget) + { + if (renderTarget) + { + renderTarget->signalDirty(); + } + } + } + + return gl::NoError(); +} + +void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + const GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = nullptr; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, + Image11 *incomingImage) +{ + const GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be + // true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage()); + } + } + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) +{ + if (mUseLevelZeroTexture && mMipLevels > 1) + { + ANGLE_TRY(ensureTextureExists(1)); + + *outResource = mLevelZeroTexture; + return gl::NoError(); + } + + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + *outResource = mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + *outResource = mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (*outputTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); + + HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", + result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture"); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + const int level = index.mipIndex; + ASSERT(level >= 0 && level < getLevelCount()); + + // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of + // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could + // create RTVs on non-zero levels of the texture (e.g. generateMipmap). + // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the + // individual levels of the texture, so methods like generateMipmap can't do anything useful + // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly + // something wrong. + ASSERT( + !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0)); + ASSERT(outRT); + if (mRenderTarget[level]) + { + *outRT = mRenderTarget[level]; + return gl::NoError(); + } + + ID3D11Resource *texture = nullptr; + ANGLE_TRY(getResource(&texture)); + + ID3D11ShaderResourceView *srv = nullptr; + ANGLE_TRY(getSRVLevel(level, false, &srv)); + + ID3D11ShaderResourceView *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(level, true, &blitSRV)); + + ID3D11Device *device = mRenderer->getDevice(); + + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget = new TextureRenderTarget11( + rtv, mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat, + getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + *outRT = mLevelZeroRenderTarget; + return gl::NoError(); + } + + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture storage, result: 0x%X.", + result); + } + + mRenderTarget[level] = new TextureRenderTarget11( + rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + + *outRT = mRenderTarget[level]; + return gl::Error(GL_NO_ERROR); + } + + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to create internal depth stencil view for texture storage, result: 0x%X.", + result); + } + + mRenderTarget[level] = + new TextureRenderTarget11(dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + + *outRT = mRenderTarget[level]; + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or + // mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast<int>(mMipLevels)); + ASSERT(mTexture != nullptr && texture == mTexture); + srvTexture = mTexture; + } + } + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV"); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); +} + +gl::Error TextureStorage11_2D::createDropStencilTexture() +{ + if (mDropStencilTexture) + { + return gl::NoError(); + } + + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = 1; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = 0; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; + + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture); + if (FAILED(hr)) + { + return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture."); + } + d3d11::SetDebugName(mDropStencilTexture, "TexStorage2D.DropStencil"); + + ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::Make2D(0, mMipLevels))); + + return gl::NoError(); +} + +TextureStorage11_External::TextureStorage11_External( + Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc) + : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat) +{ + ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12); + StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation()); + mTexture = producer->getD3DTexture(); + mSubresourceIndex = producer->getArraySlice(); + mTexture->AddRef(); + mMipLevels = 1; + + D3D11_TEXTURE2D_DESC desc; + mTexture->GetDesc(&desc); + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0; +} + +TextureStorage11_External::~TextureStorage11_External() +{ + SafeRelease(mTexture); + if (mHasKeyedMutex) + { + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); + } +} + +gl::Error TextureStorage11_External::copyToStorage(TextureStorage *destStorage) +{ + UNIMPLEMENTED(); + return gl::NoError(); +} + +void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + ASSERT(index.mipIndex == 0); + mAssociatedImage = image; +} + +bool TextureStorage11_External::isAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + return (index.mipIndex == 0 && mAssociatedImage == expectedImage); +} + +void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + ASSERT(index.mipIndex == 0); + ASSERT(mAssociatedImage == expectedImage); + mAssociatedImage = nullptr; +} + +gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::ImageIndex &index, + Image11 *incomingImage) +{ + ASSERT(index.mipIndex == 0); + + if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage) + { + bool imageAssociationCorrect = mAssociatedImage->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage()); + } + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getResource(ID3D11Resource **outResource) +{ + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_External::getMippedResource(ID3D11Resource **outResource) +{ + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_External::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + // Render targets are not supported for external textures + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_External::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and + // use the specified subresource ID the storage was created with. + ASSERT(mipLevels == 1); + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + // subresource index is equal to the mip level for 2D textures + srvDesc.Texture2DArray.MostDetailedMip = 0; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11Resource *srvTexture = texture; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV"); + + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getSwizzleTexture(ID3D11Resource **outTexture) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel, + ID3D11RenderTargetView **outRTV) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, + EGLImageD3D *eglImage, + RenderTarget11 *renderTarget11) + : TextureStorage11(renderer, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + renderTarget11->getInternalFormat()), + mImage(eglImage), + mCurrentRenderTarget(0), + mSwizzleTexture(nullptr), + mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS, nullptr) +{ + mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11); + + mMipLevels = 1; + mTextureWidth = renderTarget11->getWidth(); + mTextureHeight = renderTarget11->getHeight(); + mTextureDepth = 1; +} + +TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +{ + SafeRelease(mSwizzleTexture); + for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++) + { + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource) +{ + ANGLE_TRY(checkForUpdatedRenderTarget()); + + RenderTarget11 *renderTarget11 = nullptr; + ANGLE_TRY(getImageRenderTarget(&renderTarget11)); + *outResource = renderTarget11->getTexture(); + return gl::NoError(); +} + +gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) +{ + ANGLE_TRY(checkForUpdatedRenderTarget()); + return TextureStorage11::getSRV(textureState, outSRV); +} + +gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + // EGL images are unavailable in this configuration. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + ASSERT(index.mipIndex == 0); + + ANGLE_TRY(checkForUpdatedRenderTarget()); + + return mImage->getRenderTarget(outRT); +} + +gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage) +{ + ID3D11Resource *sourceResouce = nullptr; + ANGLE_TRY(getResource(&sourceResouce)); + + ASSERT(destStorage); + TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage); + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + + dest11->markDirty(); + + return gl::NoError(); +} + +void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &) +{ +} + +void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image11 *) +{ +} + +bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *) +{ + return false; +} + +gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *) +{ + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorageEGLImage.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel, + ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); +} + +gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() +{ + RenderTarget11 *renderTarget11 = nullptr; + ANGLE_TRY(getImageRenderTarget(&renderTarget11)); + + if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11)) + { + clearSRVCache(); + mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(baseLevel == 0); + ASSERT(mipLevels == 1); + ASSERT(outSRV); + + // Create a new SRV only for the swizzle texture. Otherwise just return the Image's + // RenderTarget's SRV. + if (texture == mSwizzleTexture) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", + result); + } + + d3d11::SetDebugName(*outSRV, "TexStorageEGLImage.SRV"); + } + else + { + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(getImageRenderTarget(&renderTarget)); + + ASSERT(texture == renderTarget->getTexture()); + + *outSRV = renderTarget->getShaderResourceView(); + (*outSRV)->AddRef(); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const +{ + RenderTargetD3D *renderTargetD3D = nullptr; + ANGLE_TRY(mImage->getRenderTarget(&renderTargetD3D)); + *outRT = GetAs<RenderTarget11>(renderTargetD3D); + return gl::NoError(); +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat), + mTexture(nullptr), + mLevelZeroTexture(nullptr), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture(nullptr) +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = nullptr; + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + mAssociatedImages[face][level] = nullptr; + mRenderTarget[face][level] = nullptr; + } + } + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + mLevelZeroRenderTarget[face] = nullptr; + } + + // adjust size if needed for compressed textures + int height = size; + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = size; + mTextureHeight = size; + mTextureDepth = 1; + + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + if (mAssociatedImages[face][level] != nullptr) + { + bool imageAssociationCorrect = + mAssociatedImages[face][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the + // TextureStorage. + mAssociatedImages[face][level]->recoverFromAssociatedStorage(); + } + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + SafeRelease(mLevelZeroTexture); + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + SafeDelete(mLevelZeroRenderTarget[face]); + } + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + SafeDelete(mRenderTarget[face][level]); + } + } +} + +UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const +{ + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && + index.mipIndex == 0) + { + UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(0, arraySlice, 1); + ASSERT(subresource != std::numeric_limits<UINT>::max()); + return subresource; + } + else + { + UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits<UINT>::max()); + return subresource; + } +} + +gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture) + { + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + } + else + { + ID3D11Resource *sourceResouce = nullptr; + ANGLE_TRY(getResource(&sourceResouce)); + + ID3D11Resource *destResource = nullptr; + ANGLE_TRY(dest11->getResource(&destResource)); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + } + + dest11->markDirty(); + + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + ANGLE_TRY(ensureTextureExists(1)); + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), + 0, 0, 0, mTexture, face * mMipLevels, nullptr); + } + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), + 0, 0, 0, mLevelZeroTexture, face, nullptr); + } + } + + mUseLevelZeroTexture = false; + } + + return gl::NoError(); +} + +void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)) + { + mAssociatedImages[layerTarget][level] = image; + } + } +} + +bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)) + { + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); + ASSERT(retValue); + return retValue; + } + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)) + { + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); + + if (mAssociatedImages[layerTarget][level] == expectedImage) + { + mAssociatedImages[layerTarget][level] = nullptr; + } + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, + Image11 *incomingImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)); + + if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) + { + if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT)) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[layerTarget][level] != nullptr && + mAssociatedImages[layerTarget][level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should + // be true. + bool imageAssociationCorrect = + mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY( + mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage()); + } + } + } + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) +{ + if (mUseLevelZeroTexture && mMipLevels > 1) + { + ANGLE_TRY(ensureTextureExists(1)); + *outResource = mLevelZeroTexture; + return gl::NoError(); + } + else + { + ANGLE_TRY(ensureTextureExists(mMipLevels)); + *outResource = mTexture; + return gl::NoError(); + } +} + +gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + ANGLE_TRY(ensureTextureExists(mMipLevels)); + *outResource = mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (*outputTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = CUBE_FACE_COUNT; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags(); + + HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create cube texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create cube texture storage, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture"); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::createRenderTargetSRV(ID3D11Resource *texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + ID3D11ShaderResourceView **srv) const +{ + ID3D11Device *device = mRenderer->getDevice(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = resourceFormat; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + } + else + { + // Will be used with Texture2D sampler, not TextureCube + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + } + + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to create internal shader resource view for texture storage, result: 0x%X.", + result); + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + const int faceIndex = index.layerIndex; + const int level = index.mipIndex; + + ASSERT(level >= 0 && level < getLevelCount()); + ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(CUBE_FACE_COUNT)); + + if (!mRenderTarget[faceIndex][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = nullptr; + ANGLE_TRY(getResource(&texture)); + + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget[faceIndex]) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11( + rtv, mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat, + getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelZeroRenderTarget[faceIndex]; + return gl::Error(GL_NO_ERROR); + } + + ID3D11ShaderResourceView *srv = nullptr; + ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv)); + ID3D11ShaderResourceView *blitSRV = nullptr; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) + { + gl::Error error = + createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV); + if (error.isError()) + { + SafeRelease(srv); + return error; + } + } + else + { + blitSRV = srv; + blitSRV->AddRef(); + } + + d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV"); + + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(rtv, "TexStorageCube.RenderTargetRTV"); + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11( + rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + SafeRelease(blitSRV); + } + else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal depth stencil view for texture " + "storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV"); + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11( + dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level), + getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + SafeRelease(blitSRV); + } + else + { + UNREACHABLE(); + } + } + + ASSERT(outRT); + *outRT = mRenderTarget[faceIndex][level]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + + // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six + // 2D textures + const GLenum componentType = d3d11::GetComponentType(format); + if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; + } + + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or + // mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast<int>(mMipLevels)); + ASSERT(mTexture != nullptr && texture == mTexture); + srvTexture = mTexture; + } + } + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outSRV, "TexStorageCube.SRV"); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = CUBE_FACE_COUNT; + desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, + ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); +} + +gl::Error TextureStorage11::initDropStencilTexture(const gl::ImageIndexIterator &it) +{ + ID3D11Resource *resource = nullptr; + ANGLE_TRY(getResource(&resource)); + TextureHelper11 sourceTexture = TextureHelper11::MakeAndReference(resource, mFormatInfo); + TextureHelper11 destTexture = TextureHelper11::MakeAndReference( + mDropStencilTexture, + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps())); + + gl::ImageIndexIterator itCopy = it; + + while (itCopy.hasNext()) + { + gl::ImageIndex index = itCopy.next(); + gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), + 1); + gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1); + UINT subresource = getSubresourceIndex(index); + ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(sourceTexture, subresource, wholeArea, + wholeSize, destTexture, subresource, + wholeArea, wholeSize, nullptr)); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::createDropStencilTexture() +{ + if (mDropStencilTexture) + { + return gl::NoError(); + } + + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = 6; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; + + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture); + if (FAILED(hr)) + { + return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture."); + } + d3d11::SetDebugName(mDropStencilTexture, "TexStorageCube.DropStencil"); + + ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::MakeCube(0, mMipLevels))); + + return gl::NoError(); +} + +TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat) +{ + mTexture = nullptr; + mSwizzleTexture = nullptr; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = nullptr; + mLevelRenderTargets[i] = nullptr; + mSwizzleRenderTargets[i] = nullptr; + } + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; +} + +TextureStorage11_3D::~TextureStorage11_3D() +{ + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != nullptr) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the + // TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); + i != mLevelLayerRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mLevelLayerRenderTargets.clear(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mLevelRenderTargets[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + const GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = nullptr; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, + Image11 *incomingImage) +{ + const GLint level = index.mipIndex; + + ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be + // true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage()); + } + } + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) +{ + // If the width, height or depth are not positive this should be treated as an incomplete + // texture. We handle that here by skipping the d3d texture creation. + if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mFormatInfo.texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); + + HRESULT result = device->CreateTexture3D(&desc, nullptr, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", + result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(mTexture, "TexStorage3D.Texture"); + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MostDetailedMip = baseLevel; + srvDesc.Texture3D.MipLevels = mipLevels; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV"); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + const int mipLevel = index.mipIndex; + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + + if (!index.hasLayer()) + { + if (!mLevelRenderTargets[mipLevel]) + { + ID3D11Resource *texture = nullptr; + ANGLE_TRY(getResource(&texture)); + + ID3D11ShaderResourceView *srv = nullptr; + ANGLE_TRY(getSRVLevel(mipLevel, false, &srv)); + + ID3D11ShaderResourceView *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = static_cast<UINT>(-1); + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(rtv, "TexStorage3D.RTV"); + + mLevelRenderTargets[mipLevel] = new TextureRenderTarget11( + rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); + } + else + { + const int layer = index.layerIndex; + + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = nullptr; + ANGLE_TRY(getResource(&texture)); + + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = nullptr; + ID3D11ShaderResourceView *blitSRV = nullptr; + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + ASSERT(SUCCEEDED(result)); + + d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV"); + + mLevelLayerRenderTargets[key] = new TextureRenderTarget11( + rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelLayerRenderTargets[key]; + return gl::NoError(); + } +} + +gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, nullptr, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = static_cast<UINT>(-1); + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleRTV"); + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat) +{ + mTexture = nullptr; + mSwizzleTexture = nullptr; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = nullptr; + } + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; +} + +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ + for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + { + if (i->second) + { + bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the + // TextureStorage. + i->second->recoverFromAssociatedStorage(); + } + } + } + mAssociatedImages.clear(); + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + } + + for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mRenderTargets.clear(); +} + +void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < getLevelCount()); + + if (0 <= level && level < getLevelCount()) + { + LevelLayerKey key(level, layerTarget); + mAssociatedImages[key] = image; + } +} + +bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && + (mAssociatedImages[key] == expectedImage)); + ASSERT(retValue); + return retValue; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && + (mAssociatedImages[key] == expectedImage)); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + mAssociatedImages[key] = nullptr; + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, + Image11 *incomingImage) +{ + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + if (mAssociatedImages.find(key) != mAssociatedImages.end()) + { + if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be + // true. + bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage()); + } + } + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) +{ + // if the width, height or depth is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); + + HRESULT result = device->CreateTexture2D(&desc, nullptr, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create 2D array texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create 2D array texture storage, result: 0x%X.", result); + } + + d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture"); + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV"); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::createRenderTargetSRV(ID3D11Resource *texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + ID3D11ShaderResourceView **srv) const +{ + ID3D11Device *device = mRenderer->getDevice(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = resourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to create internal shader resource view for texture storage, result: 0x%X.", + result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(index.hasLayer()); + + const int mipLevel = index.mipIndex; + const int layer = index.layerIndex; + + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + LevelLayerKey key(mipLevel, layer); + if (mRenderTargets.find(key) == mRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = nullptr; + ANGLE_TRY(getResource(&texture)); + ID3D11ShaderResourceView *srv; + ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv)); + ID3D11ShaderResourceView *blitSRV; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) + { + gl::Error error = + createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV); + if (error.isError()) + { + SafeRelease(srv); + return error; + } + } + else + { + blitSRV = srv; + blitSRV->AddRef(); + } + + d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV"); + + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = layer; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal render target view for texture " + "storage, result: 0x%X.", + result); + } + + d3d11::SetDebugName(rtv, "TexStorage2DArray.RenderTargetRTV"); + + mRenderTargets[key] = new TextureRenderTarget11( + rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + SafeRelease(blitSRV); + } + else + { + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + dsvDesc.Texture2DArray.FirstArraySlice = layer; + dsvDesc.Texture2DArray.ArraySize = 1; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + SafeRelease(blitSRV); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create TexStorage2DArray DSV. Result: 0x%X.", result); + } + + d3d11::SetDebugName(dsv, "TexStorage2DArray.RenderTargetDSV"); + + mRenderTargets[key] = new TextureRenderTarget11( + dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + SafeRelease(blitSRV); + } + } + + ASSERT(outRT); + *outRT = mRenderTargets[key]; + return gl::NoError(); +} + +gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, + ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); +} + +gl::Error TextureStorage11_2DArray::createDropStencilTexture() +{ + if (mDropStencilTexture) + { + return gl::NoError(); + } + + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = mTextureDepth; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = 0; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; + + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture); + if (FAILED(hr)) + { + return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture."); + } + d3d11::SetDebugName(mDropStencilTexture, "TexStorage2DArray.DropStencil"); + + std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth); + + ANGLE_TRY(initDropStencilTexture( + gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data()))); + + return gl::NoError(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h new file mode 100755 index 000000000..46eb8458b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -0,0 +1,425 @@ +// +// Copyright (c) 2012-2013 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. +// + +// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ + +#include "libANGLE/Texture.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include <array> +#include <map> + +namespace gl +{ +struct ImageIndex; +} + +namespace rx +{ +class EGLImageD3D; +class RenderTargetD3D; +class RenderTarget11; +class Renderer11; +class SwapChain11; +class Image11; +struct Renderer11DeviceCaps; + +class TextureStorage11 : public TextureStorage +{ + public: + virtual ~TextureStorage11(); + + static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget); + static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels); + + UINT getBindFlags() const; + UINT getMiscFlags() const; + + virtual gl::Error getResource(ID3D11Resource **outResource) = 0; + virtual gl::Error getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + bool supportsNativeMipmapFunction() const override; + virtual int getLevelCount() const; + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + + gl::Error generateSwizzles(const gl::SwizzleState &swizzleTarget); + void markLevelDirty(int mipLevel); + void markDirty(); + + gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, + const gl::ImageIndex &index, const gl::Box ©Area); + + gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + const gl::ImageIndex &index, const gl::Box ®ion); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0; + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + + gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV); + + const d3d11::Format &getFormatSet() const; + + protected: + TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat); + int getLevelWidth(int mipLevel) const; + int getLevelHeight(int mipLevel) const; + int getLevelDepth(int mipLevel) const; + + // Some classes (e.g. TextureStorage11_2D) will override getMippedResource. + virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); } + + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; + gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV); + + // Get a version of a depth texture with only depth information, not stencil. + virtual gl::Error createDropStencilTexture(); + gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it); + + // The baseLevel parameter should *not* have mTopLevel applied. + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const = 0; + + void verifySwizzleExists(const gl::SwizzleState &swizzleState); + + // Clear all cached non-swizzle SRVs and invalidate the swizzle cache. + void clearSRVCache(); + + Renderer11 *mRenderer; + int mTopLevel; + unsigned int mMipLevels; + + const d3d11::Format &mFormatInfo; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + unsigned int mTextureDepth; + + gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ID3D11Texture2D *mDropStencilTexture; + + private: + const UINT mBindFlags; + const UINT mMiscFlags; + + struct SRVKey + { + SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil); + + bool operator<(const SRVKey &rhs) const; + + int baseLevel = 0; // Without mTopLevel applied. + int mipLevels = 0; + bool swizzle = false; + bool dropStencil = false; + }; + typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache; + + gl::Error getCachedOrCreateSRV(const SRVKey &key, ID3D11ShaderResourceView **outSRV); + + SRVCache mSrvCache; + std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelSRVs; + std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelBlitSRVs; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); + ~TextureStorage11_2D() override; + + gl::Error getResource(ID3D11Resource **outResource) override; + gl::Error getMippedResource(ID3D11Resource **outResource) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override; + + gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override; + + protected: + gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + + gl::Error createDropStencilTexture() override; + + gl::Error ensureTextureExists(int mipLevels); + + private: + gl::Error createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const override; + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + bool mHasKeyedMutex; + + // These are members related to the zero max-LOD workaround. + // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero). + // These members are used to work around this limitation. + // Usually only mTexture XOR mLevelZeroTexture will exist. + // For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture. + // However, in some scenarios, both textures have to be created. This incurs additional memory overhead. + // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture. + // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap + // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget; + bool mUseLevelZeroTexture; + + // Swizzle-related variables + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_External : public TextureStorage11 +{ + public: + TextureStorage11_External(Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc); + ~TextureStorage11_External() override; + + gl::Error getResource(ID3D11Resource **outResource) override; + gl::Error getMippedResource(ID3D11Resource **outResource) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override; + + protected: + gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + + private: + gl::Error createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const override; + + ID3D11Texture2D *mTexture; + int mSubresourceIndex; + bool mHasKeyedMutex; + + Image11 *mAssociatedImage; +}; + +class TextureStorage11_EGLImage final : public TextureStorage11 +{ + public: + TextureStorage11_EGLImage(Renderer11 *renderer, + EGLImageD3D *eglImage, + RenderTarget11 *renderTarget11); + ~TextureStorage11_EGLImage() override; + + gl::Error getResource(ID3D11Resource **outResource) override; + gl::Error getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) override; + gl::Error getMippedResource(ID3D11Resource **outResource) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override; + + gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override; + + protected: + gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + + private: + // Check if the EGL image's render target has been updated due to orphaning and delete + // any SRVs and other resources based on the image's old render target. + gl::Error checkForUpdatedRenderTarget(); + + gl::Error createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const override; + + gl::Error getImageRenderTarget(RenderTarget11 **outRT) const; + + EGLImageD3D *mImage; + uintptr_t mCurrentRenderTarget; + + // Swizzle-related variables + ID3D11Texture2D *mSwizzleTexture; + std::vector<ID3D11RenderTargetView *> mSwizzleRenderTargets; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual ~TextureStorage11_Cube(); + + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getMippedResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + gl::Error createDropStencilTexture() override; + + gl::Error ensureTextureExists(int mipLevels); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + gl::Error createRenderTargetSRV(ID3D11Resource *texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + ID3D11ShaderResourceView **srv) const; + + static const size_t CUBE_FACE_COUNT = 6; + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT]; + bool mUseLevelZeroTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_3D : public TextureStorage11 +{ + public: + TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_3D(); + + virtual gl::Error getResource(ID3D11Resource **outResource); + + // Handles both layer and non-layer RTs + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + typedef std::pair<int, int> LevelLayerKey; + typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; + RenderTargetMap mLevelLayerRenderTargets; + + RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture3D *mTexture; + ID3D11Texture3D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2DArray : public TextureStorage11 +{ + public: + TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_2DArray(); + + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + gl::Error createDropStencilTexture() override; + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + gl::Error createRenderTargetSRV(ID3D11Resource *texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + ID3D11ShaderResourceView **srv) const; + + typedef std::pair<int, int> LevelLayerKey; + typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; + RenderTargetMap mRenderTargets; + + ID3D11Texture2D *mTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + typedef std::map<LevelLayerKey, Image11*> ImageMap; + ImageMap mAssociatedImages; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp new file mode 100755 index 000000000..39b293f9b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp @@ -0,0 +1,102 @@ +// +// Copyright 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. +// + +// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. + +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state, + Renderer11 *renderer) + : TransformFeedbackImpl(state), + mRenderer(renderer), + mIsDirty(true), + mBuffers(state.getIndexedBuffers().size(), nullptr), + mBufferOffsets(state.getIndexedBuffers().size(), 0) +{ +} + +TransformFeedback11::~TransformFeedback11() +{ +} + +void TransformFeedback11::begin(GLenum primitiveMode) +{ +} + +void TransformFeedback11::end() +{ + if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback) + { + mRenderer->getDeviceContext()->Flush(); + } +} + +void TransformFeedback11::pause() +{ +} + +void TransformFeedback11::resume() +{ +} + +void TransformFeedback11::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) +{ +} + +void TransformFeedback11::bindIndexedBuffer(size_t index, + const OffsetBindingPointer<gl::Buffer> &binding) +{ + mIsDirty = true; + mBufferOffsets[index] = static_cast<UINT>(binding.getOffset()); +} + +void TransformFeedback11::onApply() +{ + mIsDirty = false; + + // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to + // append + std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1); +} + +bool TransformFeedback11::isDirty() const +{ + return mIsDirty; +} + +UINT TransformFeedback11::getNumSOBuffers() const +{ + return static_cast<UINT>(mBuffers.size()); +} + +gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> TransformFeedback11::getSOBuffers() +{ + for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++) + { + const auto &binding = mState.getIndexedBuffer(bindingIdx); + if (binding.get() != nullptr) + { + Buffer11 *storage = GetImplAs<Buffer11>(binding.get()); + ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + mBuffers[bindingIdx]); + } + } + + return &mBuffers; +} + +const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const +{ + return mBufferOffsets; +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h new file mode 100755 index 000000000..01879d6f3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h @@ -0,0 +1,54 @@ +// +// Copyright 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. +// + +// TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ + +#include "common/platform.h" + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" + +namespace rx +{ + +class Renderer11; + +class TransformFeedback11 : public TransformFeedbackImpl +{ + public: + TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer); + ~TransformFeedback11() override; + + void begin(GLenum primitiveMode) override; + void end() override; + void pause() override; + void resume() override; + + void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override; + void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override; + + void onApply(); + + bool isDirty() const; + + UINT getNumSOBuffers() const; + gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers(); + const std::vector<UINT> &getSOBufferOffsets() const; + + private: + Renderer11 *mRenderer; + + bool mIsDirty; + std::vector<ID3D11Buffer *> mBuffers; + std::vector<UINT> mBufferOffsets; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp new file mode 100755 index 000000000..29185a9d9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 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. +// + +// Trim11.cpp: Trim support utility class. + +#include "libANGLE/renderer/d3d/d3d11/Trim11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) +#include <wrl.h> +#include <wrl/wrappers/corewrappers.h> +#include <windows.applicationmodel.core.h> +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +#endif + +namespace rx +{ + +Trim11::Trim11(rx::Renderer11 *renderer) + : mRenderer(renderer) +{ + bool result = true; + result = registerForRendererTrimRequest(); + ASSERT(result); +} + +Trim11::~Trim11() +{ + unregisterForRendererTrimRequest(); +} + +void Trim11::trim() +{ + if (!mRenderer) + { + return; + } + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ID3D11Device* device = mRenderer->getDevice(); + IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device); + if (dxgiDevice3) + { + dxgiDevice3->Trim(); + } + SafeRelease(dxgiDevice3); +#endif +} + +bool Trim11::registerForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ICoreApplication* coreApplication = nullptr; + HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication); + if (SUCCEEDED(result)) + { + auto suspendHandler = Callback<IEventHandler<SuspendingEventArgs*>>( + [this](IInspectable*, ISuspendingEventArgs*) -> HRESULT + { + trim(); + return S_OK; + }); + result = coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken); + } + SafeRelease(coreApplication); + + if (FAILED(result)) + { + return false; + } +#endif + return true; +} + +void Trim11::unregisterForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + if (mApplicationSuspendedEventToken.value != 0) + { + ICoreApplication* coreApplication = nullptr; + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication))) + { + coreApplication->remove_Suspending(mApplicationSuspendedEventToken); + } + mApplicationSuspendedEventToken.value = 0; + SafeRelease(coreApplication); + } +#endif +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h new file mode 100755 index 000000000..4741e8160 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 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. +// + +// Trim11.h: Trim support utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef void* EventRegistrationToken; +#else +#include <EventToken.h> +#endif + +namespace rx +{ +class Renderer11; + +class Trim11 : angle::NonCopyable +{ + public: + explicit Trim11(Renderer11 *renderer); + ~Trim11(); + + private: + Renderer11 *mRenderer; +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + EventRegistrationToken mApplicationSuspendedEventToken; +#endif + + void trim(); + bool registerForRendererTrimRequest(); + void unregisterForRendererTrimRequest(); +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp new file mode 100755 index 000000000..e06a6b22b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp @@ -0,0 +1,245 @@ +// +// Copyright 2016 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. +// +// VertexArray11: +// Implementation of rx::VertexArray11. +// + +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" + +#include "common/BitSetIterator.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" + +using namespace angle; + +namespace rx +{ + +namespace +{ +size_t GetAttribIndex(unsigned long dirtyBit) +{ + if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED && + dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED) + { + return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED; + } + + if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER && + dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER) + { + return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER; + } + + ASSERT(dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR && + dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR); + return static_cast<size_t>(dirtyBit) - gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR; +} +} // anonymous namespace + +VertexArray11::VertexArray11(const gl::VertexArrayState &data) + : VertexArrayImpl(data), + mAttributeStorageTypes(data.getVertexAttributes().size(), VertexStorageType::CURRENT_VALUE), + mTranslatedAttribs(data.getVertexAttributes().size()), + mCurrentBuffers(data.getVertexAttributes().size()) +{ + for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex) + { + mOnBufferDataDirty.push_back(ChannelBinding(this, static_cast<SignalToken>(attribIndex))); + } +} + +VertexArray11::~VertexArray11() +{ + for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex) + { + if (mCurrentBuffers[attribIndex].get()) + { + mCurrentBuffers[attribIndex].set(nullptr); + } + } +} + +void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits) +{ + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) + continue; + + size_t attribIndex = GetAttribIndex(dirtyBit); + mAttribsToUpdate.set(attribIndex); + } +} + +void VertexArray11::updateVertexAttribStorage(size_t attribIndex) +{ + const auto &attrib = mData.getVertexAttribute(attribIndex); + + // Note: having an unchanged storage type doesn't mean the attribute is clean. + auto oldStorageType = mAttributeStorageTypes[attribIndex]; + auto newStorageType = ClassifyAttributeStorage(attrib); + + mAttributeStorageTypes[attribIndex] = newStorageType; + + if (newStorageType == VertexStorageType::DYNAMIC) + { + if (oldStorageType != VertexStorageType::DYNAMIC) + { + // Sync dynamic attribs in a different set. + mAttribsToTranslate.reset(attribIndex); + mDynamicAttribsMask.set(attribIndex); + } + } + else + { + mAttribsToTranslate.set(attribIndex); + + if (oldStorageType == VertexStorageType::DYNAMIC) + { + ASSERT(mDynamicAttribsMask[attribIndex]); + mDynamicAttribsMask.reset(attribIndex); + } + } + + gl::Buffer *oldBufferGL = mCurrentBuffers[attribIndex].get(); + gl::Buffer *newBufferGL = attrib.buffer.get(); + Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr; + Buffer11 *newBuffer11 = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr; + + if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType) + { + // Note that for static callbacks, promotion to a static buffer from a dynamic buffer means + // we need to tag dynamic buffers with static callbacks. + BroadcastChannel *newChannel = nullptr; + if (newBuffer11 != nullptr) + { + switch (newStorageType) + { + case VertexStorageType::DIRECT: + newChannel = newBuffer11->getDirectBroadcastChannel(); + break; + case VertexStorageType::STATIC: + case VertexStorageType::DYNAMIC: + newChannel = newBuffer11->getStaticBroadcastChannel(); + break; + default: + break; + } + } + mOnBufferDataDirty[attribIndex].bind(newChannel); + mCurrentBuffers[attribIndex] = attrib.buffer; + } +} + +gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, + const gl::State &state, + GLint start, + GLsizei count, + GLsizei instances) +{ + const gl::Program *program = state.getProgram(); + const auto &activeLocations = program->getActiveAttribLocationsMask(); + + if (mAttribsToUpdate.any()) + { + // Skip attrib locations the program doesn't use. + const auto &activeToUpdate = (mAttribsToUpdate & activeLocations); + + for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate)) + { + mAttribsToUpdate.reset(toUpdateIndex); + updateVertexAttribStorage(toUpdateIndex); + } + } + + const auto &attribs = mData.getVertexAttributes(); + + if (mAttribsToTranslate.any()) + { + // Skip attrib locations the program doesn't use, saving for the next frame. + const auto &dirtyActiveAttribs = (mAttribsToTranslate & activeLocations); + + for (auto dirtyAttribIndex : angle::IterateBitSet(dirtyActiveAttribs)) + { + mAttribsToTranslate.reset(dirtyAttribIndex); + + auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex]; + const auto ¤tValue = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex)); + + // Record basic attrib info + translatedAttrib->attribute = &attribs[dirtyAttribIndex]; + translatedAttrib->currentValueType = currentValue.Type; + translatedAttrib->divisor = translatedAttrib->attribute->divisor; + + switch (mAttributeStorageTypes[dirtyAttribIndex]) + { + case VertexStorageType::DIRECT: + VertexDataManager::StoreDirectAttrib(translatedAttrib); + break; + case VertexStorageType::STATIC: + { + ANGLE_TRY( + VertexDataManager::StoreStaticAttrib(translatedAttrib, count, instances)); + break; + } + case VertexStorageType::CURRENT_VALUE: + // Current value attribs are managed by the StateManager11. + break; + default: + UNREACHABLE(); + break; + } + } + } + + if (mDynamicAttribsMask.any()) + { + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + + for (auto dynamicAttribIndex : angle::IterateBitSet(activeDynamicAttribs)) + { + auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex]; + const auto ¤tValue = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(dynamicAttribIndex)); + + // Record basic attrib info + dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; + dynamicAttrib->currentValueType = currentValue.Type; + dynamicAttrib->divisor = dynamicAttrib->attribute->divisor; + } + + return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs, + start, count, instances); + } + + return gl::Error(GL_NO_ERROR); +} + +const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const +{ + return mTranslatedAttribs; +} + +void VertexArray11::signal(SignalToken token) +{ + ASSERT(mAttributeStorageTypes[token] != VertexStorageType::CURRENT_VALUE); + + // This can change a buffer's storage, we'll need to re-check. + mAttribsToUpdate.set(token); +} + +void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count) +{ + const gl::Program *program = state.getProgram(); + const auto &activeLocations = program->getActiveAttribLocationsMask(); + mAttribsToUpdate &= ~activeLocations; + + // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness. + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h new file mode 100755 index 000000000..eb0e0595d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -0,0 +1,62 @@ +// +// Copyright 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. +// + +// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ + +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/signal_utils.h" + +namespace rx +{ +class Renderer11; + +class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver +{ + public: + VertexArray11(const gl::VertexArrayState &data); + ~VertexArray11() override; + + void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override; + gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, + const gl::State &state, + GLint start, + GLsizei count, + GLsizei instances); + void clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count); + + const std::vector<TranslatedAttribute> &getTranslatedAttribs() const; + + // SignalReceiver implementation + void signal(angle::SignalToken token) override; + + private: + void updateVertexAttribStorage(size_t attribIndex); + + std::vector<VertexStorageType> mAttributeStorageTypes; + std::vector<TranslatedAttribute> mTranslatedAttribs; + + // The mask of attributes marked as dynamic. + gl::AttributesMask mDynamicAttribsMask; + + // A mask of attributes that need to be re-evaluated. + gl::AttributesMask mAttribsToUpdate; + + // A set of attributes we know are dirty, and need to be re-translated. + gl::AttributesMask mAttribsToTranslate; + + // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks. + std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers; + + std::vector<angle::ChannelBinding> mOnBufferDataDirty; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp new file mode 100755 index 000000000..6cd91bd35 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -0,0 +1,191 @@ +// +// Copyright (c) 2013 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. +// + +// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. + +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; + mMappedResourceData = NULL; +} + +VertexBuffer11::~VertexBuffer11() +{ + ASSERT(mMappedResourceData == NULL); + SafeRelease(mBuffer); +} + +gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mBuffer); + + updateSerial(); + + if (size > 0) + { + ID3D11Device *dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to allocate internal vertex buffer of size, %lu.", size); + } + + if (dynamicUsage) + { + d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)"); + } + else + { + d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)"); + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexBuffer11::mapResource() +{ + if (mMappedResourceData == NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + + HRESULT result = + dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); + } + + mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData); + } + + return gl::Error(GL_NO_ERROR); +} + +void VertexBuffer11::hintUnmapResource() +{ + if (mMappedResourceData != NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + + mMappedResourceData = NULL; + } +} + +gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib)); + + // This will map the resource if it isn't already mapped. + ANGLE_TRY(mapResource()); + + uint8_t *output = mMappedResourceData + offset; + + const uint8_t *input = sourceData; + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); + const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = + d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); + ASSERT(vertexFormatInfo.copyFunction != NULL); + vertexFormatInfo.copyFunction(input, inputStride, count, output); + + return gl::NoError(); +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error VertexBuffer11::discard() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); + } + + dxContext->Unmap(mBuffer, 0); + + return gl::Error(GL_NO_ERROR); +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h new file mode 100755 index 000000000..e8339db49 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2012 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. +// + +// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ + +#include <stdint.h> + +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer11; + +class VertexBuffer11 : public VertexBuffer +{ + public: + explicit VertexBuffer11(Renderer11 *const renderer); + + gl::Error initialize(unsigned int size, bool dynamicUsage) override; + + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) override; + + unsigned int getBufferSize() const override; + gl::Error setBufferSize(unsigned int size) override; + gl::Error discard() override; + + void hintUnmapResource() override; + + ID3D11Buffer *getBuffer() const; + + private: + ~VertexBuffer11() override; + gl::Error mapResource(); + + Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + uint8_t *mMappedResourceData; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h new file mode 100755 index 000000000..5501e361f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013-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. +// + +// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ + +#include "common/mathutil.h" + +namespace rx +{ + +// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component) +template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits> +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t componentCount> +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +} + +#include "copyvertex.inl" + +#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl new file mode 100755 index 000000000..7c5c157c6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -0,0 +1,386 @@ +// +// Copyright (c) 2014-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. +// + +namespace rx +{ + +template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits> +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t attribSize = sizeof(T)* inputComponentCount; + + if (attribSize == stride && inputComponentCount == outputComponentCount) + { + memcpy(output, input, count * attribSize); + return; + } + + if (inputComponentCount == outputComponentCount) + { + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride)); + T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + } + return; + } + + const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride)); + T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + + if (inputComponentCount < lastNonAlphaOutputComponent) + { + // Set the remaining G/B channels to 0. + size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount); + memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T)); + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // Set the remaining alpha channel to the defaultAlphaValue. + offsetOutput[3] = defaultAlphaValue; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort*>(output)+i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast<GLshort>(offsetInput[j]); + } + + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On integer formats, we must set the Alpha channel to 1 if it's unused. + offsetOutput[3] = 1; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort*>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + // The original GLbyte value ranges from -128 to +127 (INT8_MAX). + // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX). + if (offsetInput[j] > 0) + { + offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6); + } + else + { + offsetOutput[j] = offsetInput[j] << 8; + } + } + + for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On normalized formats, we must set the Alpha channel to the max value if it's unused. + offsetOutput[3] = INT16_MAX; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (size_t i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i)); + float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor; + } + + // 4-component output formats would need special padding in the alpha channel. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + typedef std::numeric_limits<T> NL; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i)); + float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + if (normalized) + { + if (NL::is_signed) + { + const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]); + } + } + + // This would require special padding. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +namespace priv +{ + +template <bool isSigned, bool normalized, bool toFloat> +static inline void CopyPackedRGB(uint32_t data, uint8_t *output) +{ + const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit + const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 + + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast<GLfloat>(negativeNumber); + } + else + { + finalValue = static_cast<GLfloat>(data); + } + + if (normalized) + { + const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 + const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue + + // A 10-bit two's complement number has the possibility of being minValue - 1 but + // OpenGL's normalization rules dictate that it should be clamped to minValue in this + // case. + if (finalValue < minValue) + { + finalValue = minValue; + } + + const int32_t halfRange = (maxValue - minValue) >> 1; + *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; + } + else + { + *floatOutput = finalValue; + } + } + else + { + if (normalized) + { + const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 + *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue); + } + else + { + *floatOutput = static_cast<GLfloat>(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort*>(output); + + if (data & rgbSignMask) + { + *intOutput = static_cast<GLshort>(data | negativeMask); + } + else + { + *intOutput = static_cast<GLshort>(data); + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort*>(output); + *uintOutput = static_cast<GLushort>(data); + } + } +} + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyPackedAlpha(uint32_t data, uint8_t *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); + if (isSigned) + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -1.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -2.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + } + else + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f / 3.0f; break; + case 0x1: *floatOutput = 1.0f / 3.0f; break; + case 0x2: *floatOutput = 2.0f / 3.0f; break; + case 0x3: *floatOutput = 3.0f / 3.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = 2.0f; break; + case 0x3: *floatOutput = 3.0f; break; + default: UNREACHABLE(); + } + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort*>(output); + switch (data) + { + case 0x0: *intOutput = 0; break; + case 0x1: *intOutput = 1; break; + case 0x2: *intOutput = -2; break; + case 0x3: *intOutput = -1; break; + default: UNREACHABLE(); + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort*>(output); + switch (data) + { + case 0x0: *uintOutput = 0; break; + case 0x1: *uintOutput = 1; break; + case 0x2: *uintOutput = 2; break; + case 0x3: *uintOutput = 3; break; + default: UNREACHABLE(); + } + } + } +} + +} + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t outputComponentSize = toFloat ? 4 : 2; + const size_t componentCount = 4; + + const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 + const size_t redShift = 0; // red is bits 0 through 9 + const size_t greenShift = 10; // green is bits 10 through 19 + const size_t blueShift = 20; // blue is bits 20 through 29 + + const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 + const size_t alphaShift = 30; // Alpha is the 30 and 31 bits + + for (size_t i = 0; i < count; i++) + { + GLuint packedValue = *reinterpret_cast<const GLuint*>(input + (i * stride)); + uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); + + priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + priv::CopyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json new file mode 100644 index 000000000..5b8d73568 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json @@ -0,0 +1,118 @@ +{ + "UNKNOWN": "NONE", + "R32G32B32A32_TYPELESS": "", + "R32G32B32A32_FLOAT": "", + "R32G32B32A32_UINT": "", + "R32G32B32A32_SINT": "", + "R32G32B32_TYPELESS": "", + "R32G32B32_FLOAT": "", + "R32G32B32_UINT": "", + "R32G32B32_SINT": "", + "R16G16B16A16_TYPELESS": "", + "R16G16B16A16_FLOAT": "", + "R16G16B16A16_UNORM": "", + "R16G16B16A16_UINT": "", + "R16G16B16A16_SNORM": "", + "R16G16B16A16_SINT": "", + "R32G32_TYPELESS": "", + "R32G32_FLOAT": "", + "R32G32_UINT": "", + "R32G32_SINT": "", + "R32G8X24_TYPELESS": "", + "D32_FLOAT_S8X24_UINT": "", + "R32_FLOAT_X8X24_TYPELESS": "", + "X32_TYPELESS_G8X24_UINT": "", + "R10G10B10A2_TYPELESS": "", + "R10G10B10A2_UNORM": "", + "R10G10B10A2_UINT": "", + "R11G11B10_FLOAT": "", + "R8G8B8A8_TYPELESS": "", + "R8G8B8A8_UNORM": "", + "R8G8B8A8_UNORM_SRGB": "", + "R8G8B8A8_UINT": "", + "R8G8B8A8_SNORM": "", + "R8G8B8A8_SINT": "", + "R16G16_TYPELESS": "", + "R16G16_FLOAT": "", + "R16G16_UNORM": "", + "R16G16_UINT": "", + "R16G16_SNORM": "", + "R16G16_SINT": "", + "R32_TYPELESS": "", + "D32_FLOAT": "", + "R32_FLOAT": "", + "R32_UINT": "", + "R32_SINT": "", + "R24G8_TYPELESS": "", + "D24_UNORM_S8_UINT": "", + "R24_UNORM_X8_TYPELESS": "", + "X24_TYPELESS_G8_UINT": "", + "R8G8_TYPELESS": "", + "R8G8_UNORM": "", + "R8G8_UINT": "", + "R8G8_SNORM": "", + "R8G8_SINT": "", + "R16_TYPELESS": "", + "R16_FLOAT": "", + "D16_UNORM": "", + "R16_UNORM": "", + "R16_UINT": "", + "R16_SNORM": "", + "R16_SINT": "", + "R8_TYPELESS": "", + "R8_UNORM": "", + "R8_UINT": "", + "R8_SNORM": "", + "R8_SINT": "", + "A8_UNORM": "", + "R1_UNORM": "", + "R9G9B9E5_SHAREDEXP": "", + "R8G8_B8G8_UNORM": "", + "G8R8_G8B8_UNORM": "", + "BC1_TYPELESS": "", + "BC1_UNORM": "BC1_RGBA_UNORM_BLOCK", + "BC1_UNORM_SRGB": "", + "BC2_TYPELESS": "", + "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK", + "BC2_UNORM_SRGB": "", + "BC3_TYPELESS": "", + "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK", + "BC3_UNORM_SRGB": "", + "BC4_TYPELESS": "", + "BC4_UNORM": "", + "BC4_SNORM": "", + "BC5_TYPELESS": "", + "BC5_UNORM": "", + "BC5_SNORM": "", + "B5G6R5_UNORM": "", + "B5G5R5A1_UNORM": "", + "B8G8R8A8_UNORM": "", + "B8G8R8X8_UNORM": "", + "R10G10B10_XR_BIAS_A2_UNORM": "", + "B8G8R8A8_TYPELESS": "", + "B8G8R8A8_UNORM_SRGB": "", + "B8G8R8X8_TYPELESS": "", + "B8G8R8X8_UNORM_SRGB": "", + "BC6H_TYPELESS": "", + "BC6H_UF16": "", + "BC6H_SF16": "", + "BC7_TYPELESS": "", + "BC7_UNORM": "", + "BC7_UNORM_SRGB": "", + "AYUV": "", + "Y410": "", + "Y416": "", + "NV12": "", + "P010": "", + "P016": "", + "420_OPAQUE": "", + "YUY2": "", + "Y210": "", + "Y216": "", + "NV11": "", + "AI44": "", + "IA44": "", + "P8": "", + "A8P8": "", + "B4G4R4A4_UNORM": "" +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp new file mode 100644 index 000000000..66610cac9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp @@ -0,0 +1,516 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_dxgi_format_table.py using data from dxgi_format_data.json. +// +// Copyright 2016 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. +// +// DXGI format info: +// Determining metadata about a DXGI format. + +#include "libANGLE/renderer/Format.h" + +using namespace angle; + +namespace rx +{ + +namespace d3d11 +{ + +GLenum GetComponentType(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + break; + case DXGI_FORMAT_A8P8: + break; + case DXGI_FORMAT_A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_AI44: + break; + case DXGI_FORMAT_AYUV: + break; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B5G5R5A1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B5G6R5_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC1_TYPELESS: + break; + case DXGI_FORMAT_BC1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC1_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC2_TYPELESS: + break; + case DXGI_FORMAT_BC2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC2_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC3_TYPELESS: + break; + case DXGI_FORMAT_BC3_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC3_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC4_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_BC4_TYPELESS: + break; + case DXGI_FORMAT_BC4_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC5_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_BC5_TYPELESS: + break; + case DXGI_FORMAT_BC5_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC6H_SF16: + break; + case DXGI_FORMAT_BC6H_TYPELESS: + break; + case DXGI_FORMAT_BC6H_UF16: + break; + case DXGI_FORMAT_BC7_TYPELESS: + break; + case DXGI_FORMAT_BC7_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC7_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_D16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + break; + case DXGI_FORMAT_D32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + break; + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_IA44: + break; + case DXGI_FORMAT_NV11: + break; + case DXGI_FORMAT_NV12: + break; + case DXGI_FORMAT_P010: + break; + case DXGI_FORMAT_P016: + break; + case DXGI_FORMAT_P8: + break; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + break; + case DXGI_FORMAT_R10G10B10A2_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R11G11B10_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16B16A16_SINT: + return GL_INT; + case DXGI_FORMAT_R16G16B16A16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + break; + case DXGI_FORMAT_R16G16B16A16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16G16B16A16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16_SINT: + return GL_INT; + case DXGI_FORMAT_R16G16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16_TYPELESS: + break; + case DXGI_FORMAT_R16G16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16G16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16_SINT: + return GL_INT; + case DXGI_FORMAT_R16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16_TYPELESS: + break; + case DXGI_FORMAT_R16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R24G8_TYPELESS: + break; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32B32A32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G32B32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32B32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32B32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32_TYPELESS: + break; + case DXGI_FORMAT_R32G32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + return GL_FLOAT; + case DXGI_FORMAT_R32_SINT: + return GL_INT; + case DXGI_FORMAT_R32_TYPELESS: + break; + case DXGI_FORMAT_R32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8B8A8_SINT: + return GL_INT; + case DXGI_FORMAT_R8G8B8A8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + break; + case DXGI_FORMAT_R8G8B8A8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_B8G8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_SINT: + return GL_INT; + case DXGI_FORMAT_R8G8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_TYPELESS: + break; + case DXGI_FORMAT_R8G8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8_SINT: + return GL_INT; + case DXGI_FORMAT_R8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8_TYPELESS: + break; + case DXGI_FORMAT_R8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return GL_FLOAT; + case DXGI_FORMAT_UNKNOWN: + break; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_Y210: + break; + case DXGI_FORMAT_Y216: + break; + case DXGI_FORMAT_Y410: + break; + case DXGI_FORMAT_Y416: + break; + case DXGI_FORMAT_YUY2: + break; + default: + break; + } + + UNREACHABLE(); + return GL_NONE; +} + +} // namespace d3d11 + +namespace d3d11_angle +{ + +const Format &GetFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + break; + case DXGI_FORMAT_A8P8: + break; + case DXGI_FORMAT_A8_UNORM: + return Format::Get(Format::ID::A8_UNORM); + case DXGI_FORMAT_AI44: + break; + case DXGI_FORMAT_AYUV: + break; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return Format::Get(Format::ID::B4G4R4A4_UNORM); + case DXGI_FORMAT_B5G5R5A1_UNORM: + return Format::Get(Format::ID::B5G5R5A1_UNORM); + case DXGI_FORMAT_B5G6R5_UNORM: + return Format::Get(Format::ID::B5G6R5_UNORM); + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return Format::Get(Format::ID::B8G8R8A8_UNORM); + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + break; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return Format::Get(Format::ID::B8G8R8X8_UNORM); + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + break; + case DXGI_FORMAT_BC1_TYPELESS: + break; + case DXGI_FORMAT_BC1_UNORM: + return Format::Get(Format::ID::BC1_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC1_UNORM_SRGB: + break; + case DXGI_FORMAT_BC2_TYPELESS: + break; + case DXGI_FORMAT_BC2_UNORM: + return Format::Get(Format::ID::BC2_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC2_UNORM_SRGB: + break; + case DXGI_FORMAT_BC3_TYPELESS: + break; + case DXGI_FORMAT_BC3_UNORM: + return Format::Get(Format::ID::BC3_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC3_UNORM_SRGB: + break; + case DXGI_FORMAT_BC4_SNORM: + break; + case DXGI_FORMAT_BC4_TYPELESS: + break; + case DXGI_FORMAT_BC4_UNORM: + break; + case DXGI_FORMAT_BC5_SNORM: + break; + case DXGI_FORMAT_BC5_TYPELESS: + break; + case DXGI_FORMAT_BC5_UNORM: + break; + case DXGI_FORMAT_BC6H_SF16: + break; + case DXGI_FORMAT_BC6H_TYPELESS: + break; + case DXGI_FORMAT_BC6H_UF16: + break; + case DXGI_FORMAT_BC7_TYPELESS: + break; + case DXGI_FORMAT_BC7_UNORM: + break; + case DXGI_FORMAT_BC7_UNORM_SRGB: + break; + case DXGI_FORMAT_D16_UNORM: + return Format::Get(Format::ID::D16_UNORM); + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return Format::Get(Format::ID::D24_UNORM_S8_UINT); + case DXGI_FORMAT_D32_FLOAT: + return Format::Get(Format::ID::D32_FLOAT); + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return Format::Get(Format::ID::D32_FLOAT_S8X24_UINT); + case DXGI_FORMAT_G8R8_G8B8_UNORM: + break; + case DXGI_FORMAT_IA44: + break; + case DXGI_FORMAT_NV11: + break; + case DXGI_FORMAT_NV12: + break; + case DXGI_FORMAT_P010: + break; + case DXGI_FORMAT_P016: + break; + case DXGI_FORMAT_P8: + break; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + break; + case DXGI_FORMAT_R10G10B10A2_UINT: + return Format::Get(Format::ID::R10G10B10A2_UINT); + case DXGI_FORMAT_R10G10B10A2_UNORM: + return Format::Get(Format::ID::R10G10B10A2_UNORM); + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + break; + case DXGI_FORMAT_R11G11B10_FLOAT: + return Format::Get(Format::ID::R11G11B10_FLOAT); + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return Format::Get(Format::ID::R16G16B16A16_FLOAT); + case DXGI_FORMAT_R16G16B16A16_SINT: + return Format::Get(Format::ID::R16G16B16A16_SINT); + case DXGI_FORMAT_R16G16B16A16_SNORM: + return Format::Get(Format::ID::R16G16B16A16_SNORM); + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + break; + case DXGI_FORMAT_R16G16B16A16_UINT: + return Format::Get(Format::ID::R16G16B16A16_UINT); + case DXGI_FORMAT_R16G16B16A16_UNORM: + return Format::Get(Format::ID::R16G16B16A16_UNORM); + case DXGI_FORMAT_R16G16_FLOAT: + return Format::Get(Format::ID::R16G16_FLOAT); + case DXGI_FORMAT_R16G16_SINT: + return Format::Get(Format::ID::R16G16_SINT); + case DXGI_FORMAT_R16G16_SNORM: + return Format::Get(Format::ID::R16G16_SNORM); + case DXGI_FORMAT_R16G16_TYPELESS: + break; + case DXGI_FORMAT_R16G16_UINT: + return Format::Get(Format::ID::R16G16_UINT); + case DXGI_FORMAT_R16G16_UNORM: + return Format::Get(Format::ID::R16G16_UNORM); + case DXGI_FORMAT_R16_FLOAT: + return Format::Get(Format::ID::R16_FLOAT); + case DXGI_FORMAT_R16_SINT: + return Format::Get(Format::ID::R16_SINT); + case DXGI_FORMAT_R16_SNORM: + return Format::Get(Format::ID::R16_SNORM); + case DXGI_FORMAT_R16_TYPELESS: + break; + case DXGI_FORMAT_R16_UINT: + return Format::Get(Format::ID::R16_UINT); + case DXGI_FORMAT_R16_UNORM: + return Format::Get(Format::ID::R16_UNORM); + case DXGI_FORMAT_R1_UNORM: + break; + case DXGI_FORMAT_R24G8_TYPELESS: + break; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return Format::Get(Format::ID::R32G32B32A32_FLOAT); + case DXGI_FORMAT_R32G32B32A32_SINT: + return Format::Get(Format::ID::R32G32B32A32_SINT); + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_UINT: + return Format::Get(Format::ID::R32G32B32A32_UINT); + case DXGI_FORMAT_R32G32B32_FLOAT: + return Format::Get(Format::ID::R32G32B32_FLOAT); + case DXGI_FORMAT_R32G32B32_SINT: + return Format::Get(Format::ID::R32G32B32_SINT); + case DXGI_FORMAT_R32G32B32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32_UINT: + return Format::Get(Format::ID::R32G32B32_UINT); + case DXGI_FORMAT_R32G32_FLOAT: + return Format::Get(Format::ID::R32G32_FLOAT); + case DXGI_FORMAT_R32G32_SINT: + return Format::Get(Format::ID::R32G32_SINT); + case DXGI_FORMAT_R32G32_TYPELESS: + break; + case DXGI_FORMAT_R32G32_UINT: + return Format::Get(Format::ID::R32G32_UINT); + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_FLOAT: + return Format::Get(Format::ID::R32_FLOAT); + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_SINT: + return Format::Get(Format::ID::R32_SINT); + case DXGI_FORMAT_R32_TYPELESS: + break; + case DXGI_FORMAT_R32_UINT: + return Format::Get(Format::ID::R32_UINT); + case DXGI_FORMAT_R8G8B8A8_SINT: + return Format::Get(Format::ID::R8G8B8A8_SINT); + case DXGI_FORMAT_R8G8B8A8_SNORM: + return Format::Get(Format::ID::R8G8B8A8_SNORM); + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + break; + case DXGI_FORMAT_R8G8B8A8_UINT: + return Format::Get(Format::ID::R8G8B8A8_UINT); + case DXGI_FORMAT_R8G8B8A8_UNORM: + return Format::Get(Format::ID::R8G8B8A8_UNORM); + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return Format::Get(Format::ID::R8G8B8A8_UNORM_SRGB); + case DXGI_FORMAT_R8G8_B8G8_UNORM: + break; + case DXGI_FORMAT_R8G8_SINT: + return Format::Get(Format::ID::R8G8_SINT); + case DXGI_FORMAT_R8G8_SNORM: + return Format::Get(Format::ID::R8G8_SNORM); + case DXGI_FORMAT_R8G8_TYPELESS: + break; + case DXGI_FORMAT_R8G8_UINT: + return Format::Get(Format::ID::R8G8_UINT); + case DXGI_FORMAT_R8G8_UNORM: + return Format::Get(Format::ID::R8G8_UNORM); + case DXGI_FORMAT_R8_SINT: + return Format::Get(Format::ID::R8_SINT); + case DXGI_FORMAT_R8_SNORM: + return Format::Get(Format::ID::R8_SNORM); + case DXGI_FORMAT_R8_TYPELESS: + break; + case DXGI_FORMAT_R8_UINT: + return Format::Get(Format::ID::R8_UINT); + case DXGI_FORMAT_R8_UNORM: + return Format::Get(Format::ID::R8_UNORM); + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return Format::Get(Format::ID::R9G9B9E5_SHAREDEXP); + case DXGI_FORMAT_UNKNOWN: + return Format::Get(Format::ID::NONE); + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + break; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + break; + case DXGI_FORMAT_Y210: + break; + case DXGI_FORMAT_Y216: + break; + case DXGI_FORMAT_Y410: + break; + case DXGI_FORMAT_Y416: + break; + case DXGI_FORMAT_YUY2: + break; + default: + break; + } + + UNREACHABLE(); + return Format::Get(Format::ID::NONE); +} + +} // namespace d3d11_angle + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json new file mode 100755 index 000000000..dce0997d9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json @@ -0,0 +1,1279 @@ +[ + { + "DXGI_FORMAT_UNKNOWN": + { + "texture2D": "never", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32A32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32A32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R32G32B32A32_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32A32_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "11_0check", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32B32_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16B16A16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16B16A16_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "9_3check_10_0always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R16G16B16A16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R16G16B16A16_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16B16A16_SNORM": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R16G16B16A16_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R32G32_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G32_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32G8X24_TYPELESS": + { + "texture2D": "10_0", + "texture3D": "never", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_D32_FLOAT_S8X24_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "10_0", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R10G10B10A2_TYPELESS": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R10G10B10A2_UNORM": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R10G10B10A2_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R11G11B10_FLOAT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8G8B8A8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8B8A8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R8G8B8A8_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8B8A8_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8G8B8A8_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R16G16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R16G16_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16G16_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R16G16_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32_TYPELESS": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_D32_FLOAT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "10_0", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_R32_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R32_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R24G8_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_D24_UNORM_S8_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always" + }, + "DXGI_FORMAT_R24_UNORM_X8_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_X24_TYPELESS_G8_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8_UNORM": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "9_3check_10_0always", + "renderTarget": "9_3check_10_0always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8G8_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8_SNORM": + { + "texture2D": "always", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "always", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8G8_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16_FLOAT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_D16_UNORM": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R16_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R16_SNORM": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R16_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "9_3check_10_0always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8_UINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8_SNORM": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R8_SINT": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "never", + "renderTarget": "10_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_A8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "10_0" + }, + "DXGI_FORMAT_R1_UNORM": + { + "texture2D": "always", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R9G9B9E5_SHAREDEXP": + { + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R8G8_B8G8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_G8R8_G8B8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC1_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC1_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC1_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC2_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC2_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC2_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC3_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC3_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC3_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC4_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC4_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC4_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC5_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC5_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC5_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B5G6R5_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "dxgi1_2", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" + }, + "DXGI_FORMAT_B5G5R5A1_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" + }, + "DXGI_FORMAT_B8G8R8A8_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "9_3always_10_0check11_0always", + "renderTarget": "9_3always_10_0check11_0always", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "always" + }, + "DXGI_FORMAT_B8G8R8X8_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B8G8R8A8_TYPELESS": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B8G8R8X8_TYPELESS": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC6H_TYPELESS": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC6H_UF16": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC6H_SF16": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC7_TYPELESS": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC7_UNORM": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_BC7_UNORM_SRGB": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_AYUV": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_Y410": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_Y416": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_NV12": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_P010": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_P016": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_420_OPAQUE": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_YUY2": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_Y210": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_Y216": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_NV11": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_AI44": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_IA44": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_P8": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_A8P8": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never", + "mipAutoGen": "never" + }, + "DXGI_FORMAT_B4G4R4A4_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" + } + } +] diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp new file mode 100755 index 000000000..d202ce130 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp @@ -0,0 +1,2447 @@ +// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json. +// +// Copyright 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. +// +// dxgi_support_table: +// Queries for DXGI support of various texture formats. Depends on DXGI +// version, D3D feature level, and is sometimes guaranteed or optional. +// + +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" + +#include "common/debug.h" + +namespace rx +{ + +namespace d3d11 +{ + +#define F_2D D3D11_FORMAT_SUPPORT_TEXTURE2D +#define F_3D D3D11_FORMAT_SUPPORT_TEXTURE3D +#define F_CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE +#define F_SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE +#define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET +#define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET +#define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL +#define F_MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN + +namespace +{ + +const DXGISupport &GetDefaultSupport() +{ + static UINT AllSupportFlags = + D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D | + D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | + D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET | + D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; + static const DXGISupport defaultSupport(0, 0, AllSupportFlags); + return defaultSupport; +} + +const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(0, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(0, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +} + +#undef F_2D +#undef F_3D +#undef F_CUBE +#undef F_SAMPLE +#undef F_RT +#undef F_MS +#undef F_DS +#undef F_MIPGEN + +const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_9_3: + return GetDXGISupport_9_3(dxgiFormat); + case D3D_FEATURE_LEVEL_10_0: + return GetDXGISupport_10_0(dxgiFormat); + case D3D_FEATURE_LEVEL_10_1: + return GetDXGISupport_10_1(dxgiFormat); + case D3D_FEATURE_LEVEL_11_0: + return GetDXGISupport_11_0(dxgiFormat); + default: + return GetDefaultSupport(); + } +} + +} // namespace d3d11 + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h new file mode 100755 index 000000000..4abae478b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h @@ -0,0 +1,49 @@ +// +// Copyright 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. +// +// dxgi_support_table: +// Queries for DXGI support of various texture formats. Depends on DXGI +// version, D3D feature level, and is sometimes guaranteed or optional. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DXGISUPPORTTABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DXGISUPPORTTABLE_H_ + +#include "common/platform.h" + +namespace rx +{ + +namespace d3d11 +{ + +struct DXGISupport +{ + DXGISupport() + : alwaysSupportedFlags(0), + neverSupportedFlags(0), + optionallySupportedFlags(0) + { + } + + DXGISupport(UINT alwaysSupportedIn, UINT neverSupportedIn, UINT optionallySupportedIn) + : alwaysSupportedFlags(alwaysSupportedIn), + neverSupportedFlags(neverSupportedIn), + optionallySupportedFlags(optionallySupportedIn) + { + } + + UINT alwaysSupportedFlags; + UINT neverSupportedFlags; + UINT optionallySupportedFlags; +}; + +const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DXGISUPPORTTABLE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp new file mode 100755 index 000000000..695ad468d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -0,0 +1,1023 @@ +// +// Copyright (c) 2013-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. +// + +// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 +// formats. + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/copyvertex.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +namespace d3d11 +{ + +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) +{ + const auto &support = GetDXGISupport(dxgiFormat, featureLevel); + ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0); + return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0); +} + +DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight) + : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight) +{ +} + +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format) +{ + static const DXGIFormatSize sizeUnknown(0, 0, 0); + static const DXGIFormatSize size128(128, 1, 1); + static const DXGIFormatSize size96(96, 1, 1); + static const DXGIFormatSize size64(64, 1, 1); + static const DXGIFormatSize size32(32, 1, 1); + static const DXGIFormatSize size16(16, 1, 1); + static const DXGIFormatSize size8(8, 1, 1); + static const DXGIFormatSize sizeBC1(64, 4, 4); + static const DXGIFormatSize sizeBC2(128, 4, 4); + static const DXGIFormatSize sizeBC3(128, 4, 4); + static const DXGIFormatSize sizeBC4(64, 4, 4); + static const DXGIFormatSize sizeBC5(128, 4, 4); + static const DXGIFormatSize sizeBC6H(128, 4, 4); + static const DXGIFormatSize sizeBC7(128, 4, 4); + switch (format) + { + case DXGI_FORMAT_UNKNOWN: + return sizeUnknown; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return size128; + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return size96; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return size64; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return size32; + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + return size16; + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return size8; + case DXGI_FORMAT_R1_UNORM: + UNREACHABLE(); + return sizeUnknown; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return size32; + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return sizeBC1; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + return sizeBC2; + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return sizeBC3; + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return sizeBC4; + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return sizeBC5; + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return size16; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return size32; + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + return sizeBC6H; + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return sizeBC7; + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_YUY2: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + case DXGI_FORMAT_NV11: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + UNREACHABLE(); + return sizeUnknown; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return size16; + default: + UNREACHABLE(); + return sizeUnknown; + } +} + +constexpr VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(NULL) +{ +} + +constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, + DXGI_FORMAT nativeFormatIn, + VertexCopyFunction copyFunctionIn) + : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn) +{ +} + +const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType) +{ + // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature + // Level 10_0+. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx + + switch (vertexFormatType) + { + // GL_BYTE -- unnormalized + case gl::VERTEX_FORMAT_SBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &Copy8SintTo16SintVertexData<1, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &Copy8SintTo16SintVertexData<2, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &Copy8SintTo16SintVertexData<3, 4>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &Copy8SintTo16SintVertexData<4, 4>); + return &info; + } + + // GL_BYTE -- normalized + case gl::VERTEX_FORMAT_SBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &Copy8SnormTo16SnormVertexData<1, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &Copy8SnormTo16SnormVertexData<2, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, + &Copy8SnormTo16SnormVertexData<3, 4>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, + &Copy8SnormTo16SnormVertexData<4, 4>); + return &info; + } + + // GL_UNSIGNED_BYTE -- un-normalized + // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format + // table. + case gl::VERTEX_FORMAT_UBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 1, 4, 1>); + return &info; + } + case gl::VERTEX_FORMAT_UBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 2, 4, 1>); + return &info; + } + + // GL_UNSIGNED_BYTE -- normalized + // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. + + // GL_UNSIGNED_BYTE -- normalized + case gl::VERTEX_FORMAT_UBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>); + return &info; + } + case gl::VERTEX_FORMAT_UBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>); + return &info; + } + + // GL_SHORT -- un-normalized + // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. + case gl::VERTEX_FORMAT_SSHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &CopyNativeVertexData<GLshort, 1, 2, 0>); + return &info; + } + + // GL_SHORT -- normalized + // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. + case gl::VERTEX_FORMAT_SSHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &CopyNativeVertexData<GLshort, 1, 2, 0>); + return &info; + } + + // GL_UNSIGNED_SHORT -- un-normalized + case gl::VERTEX_FORMAT_USHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLushort, 1, 2, false>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLushort, 2, 2, false>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData<GLushort, 3, 3, false>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData<GLushort, 4, 4, false>); + return &info; + } + + // GL_UNSIGNED_SHORT -- normalized + case gl::VERTEX_FORMAT_USHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLushort, 1, 2, true>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLushort, 2, 2, true>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData<GLushort, 3, 3, true>); + return &info; + } + case gl::VERTEX_FORMAT_USHORT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData<GLushort, 4, 4, true>); + return &info; + } + + // GL_FIXED + // TODO: Add test to verify that this works correctly. + // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. + case gl::VERTEX_FORMAT_FIXED1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &Copy32FixedTo32FVertexData<1, 2>); + return &info; + } + + // GL_FLOAT + // TODO: Add test to verify that this works correctly. + // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. + case gl::VERTEX_FORMAT_FLOAT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyNativeVertexData<GLfloat, 1, 2, 0>); + return &info; + } + + default: + return nullptr; + } +} + +const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel) +{ + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType); + if (result) + { + return *result; + } + } + + switch (vertexFormatType) + { + // + // Float formats + // + + // GL_BYTE -- un-normalized + case gl::VERTEX_FORMAT_SBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, + &CopyNativeVertexData<GLbyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, + &CopyNativeVertexData<GLbyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData<GLbyte, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData<GLbyte, 4, 4, 0>); + return info; + } + + // GL_BYTE -- normalized + case gl::VERTEX_FORMAT_SBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, + &CopyNativeVertexData<GLbyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, + &CopyNativeVertexData<GLbyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, + &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, + &CopyNativeVertexData<GLbyte, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_BYTE -- un-normalized + case gl::VERTEX_FORMAT_UBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, + &CopyNativeVertexData<GLubyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, + &CopyNativeVertexData<GLubyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_BYTE -- normalized + case gl::VERTEX_FORMAT_UBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, + &CopyNativeVertexData<GLubyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, + &CopyNativeVertexData<GLubyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData<GLubyte, 4, 4, 0>); + return info; + } + + // GL_SHORT -- un-normalized + case gl::VERTEX_FORMAT_SSHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, + &CopyNativeVertexData<GLshort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, + &CopyNativeVertexData<GLshort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData<GLshort, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData<GLshort, 4, 4, 0>); + return info; + } + + // GL_SHORT -- normalized + case gl::VERTEX_FORMAT_SSHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, + &CopyNativeVertexData<GLshort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, + &CopyNativeVertexData<GLshort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, + &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, + &CopyNativeVertexData<GLshort, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_SHORT -- un-normalized + case gl::VERTEX_FORMAT_USHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, + &CopyNativeVertexData<GLushort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, + &CopyNativeVertexData<GLushort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData<GLushort, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_USHORT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData<GLushort, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_SHORT -- normalized + case gl::VERTEX_FORMAT_USHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, + &CopyNativeVertexData<GLushort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, + &CopyNativeVertexData<GLushort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, + &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>); + return info; + } + case gl::VERTEX_FORMAT_USHORT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, + &CopyNativeVertexData<GLushort, 4, 4, 0>); + return info; + } + + // GL_INT -- un-normalized + case gl::VERTEX_FORMAT_SINT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, + &CopyNativeVertexData<GLint, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, + &CopyNativeVertexData<GLint, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, + &CopyNativeVertexData<GLint, 3, 3, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, + &CopyNativeVertexData<GLint, 4, 4, 0>); + return info; + } + + // GL_INT -- normalized + case gl::VERTEX_FORMAT_SINT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, + &CopyTo32FVertexData<GLint, 1, 1, true>); + return info; + } + case gl::VERTEX_FORMAT_SINT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLint, 2, 2, true>); + return info; + } + case gl::VERTEX_FORMAT_SINT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData<GLint, 3, 3, true>); + return info; + } + case gl::VERTEX_FORMAT_SINT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData<GLint, 4, 4, true>); + return info; + } + + // GL_UNSIGNED_INT -- un-normalized + case gl::VERTEX_FORMAT_UINT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, + &CopyNativeVertexData<GLuint, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, + &CopyNativeVertexData<GLuint, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, + &CopyNativeVertexData<GLuint, 3, 3, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, + &CopyNativeVertexData<GLuint, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_INT -- normalized + case gl::VERTEX_FORMAT_UINT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, + &CopyTo32FVertexData<GLuint, 1, 1, true>); + return info; + } + case gl::VERTEX_FORMAT_UINT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData<GLuint, 2, 2, true>); + return info; + } + case gl::VERTEX_FORMAT_UINT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData<GLuint, 3, 3, true>); + return info; + } + case gl::VERTEX_FORMAT_UINT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData<GLuint, 4, 4, true>); + return info; + } + + // GL_FIXED + case gl::VERTEX_FORMAT_FIXED1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, + &Copy32FixedTo32FVertexData<1, 1>); + return info; + } + case gl::VERTEX_FORMAT_FIXED2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &Copy32FixedTo32FVertexData<2, 2>); + return info; + } + case gl::VERTEX_FORMAT_FIXED3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &Copy32FixedTo32FVertexData<3, 3>); + return info; + } + case gl::VERTEX_FORMAT_FIXED4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &Copy32FixedTo32FVertexData<4, 4>); + return info; + } + + // GL_HALF_FLOAT + case gl::VERTEX_FORMAT_HALF1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, + &CopyNativeVertexData<GLhalf, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_HALF2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, + &CopyNativeVertexData<GLhalf, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_HALF3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, + &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>); + return info; + } + case gl::VERTEX_FORMAT_HALF4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, + &CopyNativeVertexData<GLhalf, 4, 4, 0>); + return info; + } + + // GL_FLOAT + case gl::VERTEX_FORMAT_FLOAT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, + &CopyNativeVertexData<GLfloat, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_FLOAT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, + &CopyNativeVertexData<GLfloat, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_FLOAT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyNativeVertexData<GLfloat, 3, 3, 0>); + return info; + } + case gl::VERTEX_FORMAT_FLOAT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyNativeVertexData<GLfloat, 4, 4, 0>); + return info; + } + + // GL_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_SINT210: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>); + return info; + } + case gl::VERTEX_FORMAT_SINT210_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>); + return info; + } + + // GL_UNSIGNED_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_UINT210: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>); + return info; + } + case gl::VERTEX_FORMAT_UINT210_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, + &CopyNativeVertexData<GLuint, 1, 1, 0>); + return info; + } + + // + // Integer Formats + // + + // GL_BYTE + case gl::VERTEX_FORMAT_SBYTE1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, + &CopyNativeVertexData<GLbyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, + &CopyNativeVertexData<GLbyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData<GLbyte, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData<GLbyte, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_BYTE + case gl::VERTEX_FORMAT_UBYTE1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, + &CopyNativeVertexData<GLubyte, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, + &CopyNativeVertexData<GLubyte, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 4, 4, 0>); + return info; + } + + // GL_SHORT + case gl::VERTEX_FORMAT_SSHORT1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, + &CopyNativeVertexData<GLshort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, + &CopyNativeVertexData<GLshort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData<GLshort, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData<GLshort, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_SHORT + case gl::VERTEX_FORMAT_USHORT1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, + &CopyNativeVertexData<GLushort, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, + &CopyNativeVertexData<GLushort, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_USHORT3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData<GLushort, 3, 4, 1>); + return info; + } + case gl::VERTEX_FORMAT_USHORT4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData<GLushort, 4, 4, 0>); + return info; + } + + // GL_INT + case gl::VERTEX_FORMAT_SINT1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, + &CopyNativeVertexData<GLint, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, + &CopyNativeVertexData<GLint, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, + &CopyNativeVertexData<GLint, 3, 3, 0>); + return info; + } + case gl::VERTEX_FORMAT_SINT4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, + &CopyNativeVertexData<GLint, 4, 4, 0>); + return info; + } + + // GL_UNSIGNED_INT + case gl::VERTEX_FORMAT_UINT1_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, + &CopyNativeVertexData<GLuint, 1, 1, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT2_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, + &CopyNativeVertexData<GLuint, 2, 2, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT3_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, + &CopyNativeVertexData<GLuint, 3, 3, 0>); + return info; + } + case gl::VERTEX_FORMAT_UINT4_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, + &CopyNativeVertexData<GLuint, 4, 4, 0>); + return info; + } + + // GL_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_SINT210_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>); + return info; + } + + // GL_UNSIGNED_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_UINT210_INT: + { + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, + &CopyNativeVertexData<GLuint, 1, 1, 0>); + return info; + } + + default: + { + static constexpr VertexFormat info; + return info; + } + } +} + +} // namespace d3d11 + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h new file mode 100755 index 000000000..3a9fd63df --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2013-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. +// + +// formatutils11.h: Queries for GL image formats and their translations to D3D11 +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ + +#include <map> + +#include "common/platform.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" + +namespace rx +{ +struct Renderer11DeviceCaps; + +namespace d3d11 +{ + +// A texture might be stored as DXGI_FORMAT_R16_TYPELESS but store integer components, +// which are accessed through an DXGI_FORMAT_R16_SINT view. It's easy to write code which queries +// information about the wrong format. Therefore, use of this should be avoided where possible. + +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel); + +struct DXGIFormatSize +{ + DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight); + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; +}; +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format); + +struct VertexFormat : angle::NonCopyable +{ + constexpr VertexFormat(); + constexpr VertexFormat(VertexConversionType conversionType, + DXGI_FORMAT nativeFormat, + VertexCopyFunction copyFunction); + + VertexConversionType conversionType; + DXGI_FORMAT nativeFormat; + VertexCopyFunction copyFunction; +}; + +const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, + D3D_FEATURE_LEVEL featureLevel); + +// Auto-generated in dxgi_format_map_autogen.cpp. +GLenum GetComponentType(DXGI_FORMAT dxgiFormat); + +} // namespace d3d11 + +namespace d3d11_angle +{ +const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat); +} + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py new file mode 100644 index 000000000..6c6d1906a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py @@ -0,0 +1,134 @@ +#!/usr/bin/python +# Copyright 2016 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. +# +# gen_dxgi_format_table.py: +# Code generation for DXGI format map. + +from datetime import date +import sys + +sys.path.append('../..') +import angle_format + +template_cpp = """// GENERATED FILE - DO NOT EDIT. +// Generated by {script_name} using data from {data_source_name}. +// +// Copyright {copyright_year} 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. +// +// DXGI format info: +// Determining metadata about a DXGI format. + +#include "libANGLE/renderer/Format.h" + +using namespace angle; + +namespace rx +{{ + +namespace d3d11 +{{ + +GLenum GetComponentType(DXGI_FORMAT dxgiFormat) +{{ + switch (dxgiFormat) + {{ +{component_type_cases} default: + break; + }} + + UNREACHABLE(); + return GL_NONE; +}} + +}} // namespace d3d11 + +namespace d3d11_angle +{{ + +const Format &GetFormat(DXGI_FORMAT dxgiFormat) +{{ + switch (dxgiFormat) + {{ +{format_cases} default: + break; + }} + + UNREACHABLE(); + return Format::Get(Format::ID::NONE); +}} + +}} // namespace d3d11_angle + +}} // namespace rx +""" + +template_format_case = """ case DXGI_FORMAT_{dxgi_format}: + return {result}; +""" + +template_undefined_case = """ case DXGI_FORMAT_{dxgi_format}: + break; +""" + +def format_case(dxgi_format, result): + return template_format_case.format( + dxgi_format = dxgi_format, + result = result) + +def undefined_case(dxgi_format): + return template_undefined_case.format(dxgi_format = dxgi_format) + +component_cases = "" +format_cases = "" + +input_data = 'dxgi_format_data.json' + +dxgi_map = angle_format.load_json(input_data) + +types = { + 'SNORM': 'GL_SIGNED_NORMALIZED', + 'UNORM': 'GL_UNSIGNED_NORMALIZED', + 'SINT': 'GL_INT', + 'UINT': 'GL_UNSIGNED_INT', + 'FLOAT': 'GL_FLOAT', + 'SHAREDEXP': 'GL_FLOAT' +} + +angle_to_gl = angle_format.load_inverse_table('../../angle_format_map.json') +all_angle = angle_to_gl.keys() + +for dxgi_format, angle_format in sorted(dxgi_map.iteritems()): + + found = [ctype in dxgi_format for ctype in types.keys()] + count = reduce((lambda a, b: int(a) + int(b)), found) + + component_type = 'GL_NONE' + + if count == 1: + gltype = next(gltype for ctype, gltype in types.iteritems() if ctype in dxgi_format) + component_cases += format_case(dxgi_format, gltype) + else: + component_cases += undefined_case(dxgi_format) + + if angle_format == "": + angle_format = dxgi_format + + if angle_format in all_angle: + angle_format = "Format::Get(Format::ID::" + angle_format + ")" + format_cases += format_case(dxgi_format, angle_format) + else: + format_cases += undefined_case(dxgi_format) + +with open('dxgi_format_map_autogen.cpp', 'wt') as out_file: + output_cpp = template_cpp.format( + script_name = sys.argv[0], + data_source_name = input_data, + copyright_year = date.today().year, + component_type_cases = component_cases, + format_cases = format_cases) + out_file.write(output_cpp) + out_file.close() diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py new file mode 100755 index 000000000..dba583f1e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py @@ -0,0 +1,281 @@ +#!/usr/bin/python +# Copyright 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. +# +# gen_dxgi_support_tables.py: +# Code generation for the DXGI support tables. Determines which formats +# are natively support in D3D10+. +# +# MSDN links: +# 10_0: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627090.aspx +# 10_1: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627091.aspx +# 11_0: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325.aspx +# 11_1: https://msdn.microsoft.com/en-us/library/windows/desktop/hh404483.aspx + +import sys +import json + +macro_prefix = 'F_' + +template = """// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json. +// +// Copyright 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. +// +// dxgi_support_table: +// Queries for DXGI support of various texture formats. Depends on DXGI +// version, D3D feature level, and is sometimes guaranteed or optional. +// + +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" + +#include "common/debug.h" + +namespace rx +{{ + +namespace d3d11 +{{ + +#define {prefix}2D D3D11_FORMAT_SUPPORT_TEXTURE2D +#define {prefix}3D D3D11_FORMAT_SUPPORT_TEXTURE3D +#define {prefix}CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE +#define {prefix}SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE +#define {prefix}RT D3D11_FORMAT_SUPPORT_RENDER_TARGET +#define {prefix}MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET +#define {prefix}DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL +#define {prefix}MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN + +namespace +{{ + +const DXGISupport &GetDefaultSupport() +{{ + static UINT AllSupportFlags = + D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D | + D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | + D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET | + D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; + static const DXGISupport defaultSupport(0, 0, AllSupportFlags); + return defaultSupport; +}} + +const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat) +{{ + // clang-format off + switch (dxgiFormat) + {{ +{table_data_9_3} + default: + UNREACHABLE(); + return GetDefaultSupport(); + }} + // clang-format on +}} + +const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) +{{ + // clang-format off + switch (dxgiFormat) + {{ +{table_data_10_0} + default: + UNREACHABLE(); + return GetDefaultSupport(); + }} + // clang-format on +}} + +const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) +{{ + // clang-format off + switch (dxgiFormat) + {{ +{table_data_10_1} + default: + UNREACHABLE(); + return GetDefaultSupport(); + }} + // clang-format on +}} + +const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) +{{ + // clang-format off + switch (dxgiFormat) + {{ +{table_data_11_0} + default: + UNREACHABLE(); + return GetDefaultSupport(); + }} + // clang-format on +}} + +}} + +#undef {prefix}2D +#undef {prefix}3D +#undef {prefix}CUBE +#undef {prefix}SAMPLE +#undef {prefix}RT +#undef {prefix}MS +#undef {prefix}DS +#undef {prefix}MIPGEN + +const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) +{{ + switch (featureLevel) + {{ + case D3D_FEATURE_LEVEL_9_3: + return GetDXGISupport_9_3(dxgiFormat); + case D3D_FEATURE_LEVEL_10_0: + return GetDXGISupport_10_0(dxgiFormat); + case D3D_FEATURE_LEVEL_10_1: + return GetDXGISupport_10_1(dxgiFormat); + case D3D_FEATURE_LEVEL_11_0: + return GetDXGISupport_11_0(dxgiFormat); + default: + return GetDefaultSupport(); + }} +}} + +}} // namespace d3d11 + +}} // namespace rx +""" + +table_init = "" + +def do_format(format_data): + table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''} + + json_flag_to_d3d = { + 'texture2D': macro_prefix + '2D', + 'texture3D': macro_prefix + '3D', + 'textureCube': macro_prefix + 'CUBE', + 'shaderSample': macro_prefix + 'SAMPLE', + 'renderTarget': macro_prefix + 'RT', + 'multisampleRT': macro_prefix + 'MS', + 'depthStencil': macro_prefix + 'DS', + 'mipAutoGen': macro_prefix + 'MIPGEN' + } + + for format_name, format_support in sorted(format_data.iteritems()): + + always_supported = set() + never_supported = set() + optionally_supported = set() + fl_9_3_supported = set() + fl_9_3_check = set() + fl_10_0_supported = set() + fl_10_1_supported = set() + fl_11_0_supported = set() + fl_11_0_check = set() + fl_10_0_check_10_1_supported = set() + fl_10_0_check_11_0_supported = set() + + for json_flag, support in format_support.iteritems(): + + d3d_flag = [json_flag_to_d3d[json_flag]] + + if support == 'check': + optionally_supported.update(d3d_flag) + elif support == 'always': + always_supported.update(d3d_flag) + elif support == 'never': + never_supported.update(d3d_flag) + elif support == '10_0': + fl_10_0_supported.update(d3d_flag) + elif support == '10_1': + fl_10_1_supported.update(d3d_flag) + elif support == '11_0': + fl_11_0_supported.update(d3d_flag) + elif support == '11_1': + # TODO(jmadill): D3D 11.1 handling + never_supported.update(d3d_flag) + elif support == 'dxgi1_2': + # TODO(jmadill): DXGI 1.2 handling. + always_supported.update(d3d_flag) + elif support == '10_0check10_1always': + fl_10_0_check_10_1_supported.update(d3d_flag) + elif support == '10_0check11_0always': + fl_10_0_check_11_0_supported.update(d3d_flag) + elif support == '11_0check': + fl_11_0_check.update(d3d_flag) + elif support == '9_3always_10_0check11_0always': + fl_9_3_supported.update(d3d_flag) + fl_10_0_check_11_0_supported.update(d3d_flag) + elif support == '9_3check_10_0always': + fl_9_3_check.update(d3d_flag) + fl_10_0_supported.update(d3d_flag) + else: + print("Data specification error: " + support) + sys.exit(1) + + for feature_level in ['9_3', '10_0', '10_1', '11_0']: + always_for_fl = always_supported + optional_for_fl = optionally_supported + if feature_level == '9_3': + always_for_fl = fl_9_3_supported.union(always_for_fl) + optional_for_fl = fl_9_3_check.union(optional_for_fl) + elif feature_level == '10_0': + always_for_fl = fl_10_0_supported.union(always_for_fl) + optional_for_fl = fl_10_0_check_10_1_supported.union(optional_for_fl) + optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl) + elif feature_level == '10_1': + always_for_fl = fl_10_0_supported.union(always_for_fl) + always_for_fl = fl_10_1_supported.union(always_for_fl) + always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl) + optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl) + elif feature_level == '11_0': + always_for_fl = fl_10_0_supported.union(always_for_fl) + always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl) + always_for_fl = fl_10_0_check_11_0_supported.union(always_for_fl) + always_for_fl = fl_10_1_supported.union(always_for_fl) + always_for_fl = fl_11_0_supported.union(always_for_fl) + + always = ' | '.join(sorted(always_for_fl)) + never = ' | '.join(sorted(never_supported)) + optional = ' | '.join(sorted(optional_for_fl)) + + if not always: always = '0' + if not never: never = '0' + if not optional: optional = '0' + + table_data[feature_level] += ' case ' + format_name + ':\n' + table_data[feature_level] += ' {\n' + table_data[feature_level] += ' static const DXGISupport info(' + always + ', ' + never + ', ' + optional + ');\n' + table_data[feature_level] += ' return info;\n' + table_data[feature_level] += ' }\n' + + return table_data + +def join_table_data(table_data_1, table_data_2): + return {'9_3': table_data_1['9_3'] + table_data_2['9_3'], + '10_0': table_data_1['10_0'] + table_data_2['10_0'], + '10_1': table_data_1['10_1'] + table_data_2['10_1'], + '11_0': table_data_1['11_0'] + table_data_2['11_0']} + +with open('dxgi_support_data.json') as dxgi_file: + file_data = dxgi_file.read() + dxgi_file.close() + json_data = json.loads(file_data) + + table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''} + + for format_data in json_data: + table_data = join_table_data(table_data, do_format(format_data)) + + out_data = template.format(prefix=macro_prefix, + table_data_9_3=table_data['9_3'], + table_data_10_0=table_data['10_0'], + table_data_10_1=table_data['10_1'], + table_data_11_0=table_data['11_0']) + + with open('dxgi_support_table.cpp', 'wt') as out_file: + out_file.write(out_data) + out_file.close() + diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py new file mode 100755 index 000000000..3c4b228e4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py @@ -0,0 +1,360 @@ +#!/usr/bin/python +# Copyright 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. +# +# gen_texture_format_table.py: +# Code generation for texture format map +# + +from datetime import date +import json +import math +import pprint +import os +import re +import sys + +sys.path.append('../..') +import angle_format + +template_texture_format_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. +// Generated by {script_name} using data from {data_source_name} +// +// Copyright {copyright_year} 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. +// +// texture_format_table: +// Queries for full textureFormat information based in internalFormat +// + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.h" + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" + +using namespace angle; + +namespace rx +{{ + +namespace d3d11 +{{ + +// static +const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) +{{ + // clang-format off + switch (internalFormat) + {{ +{angle_format_info_cases} + default: + break; + }} + // clang-format on + + UNREACHABLE(); + static constexpr Format defaultInfo; + return defaultInfo; +}} + +}} // namespace d3d11 + +}} // namespace rx +""" + +# TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well. +def gl_format_channels(internal_format): + if internal_format == 'GL_BGR5_A1_ANGLEX': + return 'bgra' + if internal_format == 'GL_R11F_G11F_B10F': + return 'rgb' + if internal_format == 'GL_RGB5_A1': + return 'rgba' + if internal_format.find('GL_RGB10_A2') == 0: + return 'rgba' + + channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)') + match = re.search(channels_pattern, internal_format) + channels_string = match.group(4) + + if channels_string == 'ALPHA': + return 'a' + if channels_string == 'LUMINANCE': + if (internal_format.find('ALPHA') >= 0): + return 'la' + return 'l' + if channels_string == 'SRGB': + if (internal_format.find('ALPHA') >= 0): + return 'rgba' + return 'rgb' + if channels_string == 'DEPTH': + if (internal_format.find('STENCIL') >= 0): + return 'ds' + return 'd' + if channels_string == 'STENCIL': + return 's' + return channels_string.lower() + +def get_internal_format_initializer(internal_format, angle_format): + internal_format_initializer = 'nullptr' + gl_channels = gl_format_channels(internal_format) + gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l' + if gl_format_no_alpha and angle_format['channels'] == 'rgba': + if angle_format['texFormat'] == 'DXGI_FORMAT_BC1_UNORM': + # BC1 is a special case since the texture data determines whether each block has an alpha channel or not. + # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess. + # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general. + # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt + pass + elif 'componentType' not in angle_format: + raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format) + elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 8: + internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>' + elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 8: + internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>' + elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 16: + internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>' + elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 8: + internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>' + elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 8: + internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>' + elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 16: + internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>' + elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 16: + internal_format_initializer = 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>' + elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 16: + internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>' + elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 16: + internal_format_initializer = 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>' + elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 32: + internal_format_initializer = 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>' + elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 32: + internal_format_initializer = 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>' + elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 32: + internal_format_initializer = 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>' + else: + raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format) + + return internal_format_initializer + +def get_swizzle_format_id(internal_format, angle_format): + angle_format_id = angle_format["formatName"] + if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'): + return 'GL_NONE' + + elif 'swizzleFormat' in angle_format: + # For some special formats like compressed formats that don't have a clearly defined number + # of bits per channel, swizzle format needs to be specified manually. + return angle_format['swizzleFormat'] + + if 'bits' not in angle_format: + raise ValueError('no bits information for determining swizzleformat for format: ' + internal_format) + + bits = angle_format['bits'] + max_component_bits = max(bits.itervalues()) + channels_different = not all([component_bits == bits.itervalues().next() for component_bits in bits.itervalues()]) + + # The format itself can be used for swizzles if it can be accessed as a render target and + # sampled and the bit count for all 4 channels is the same. + if "rtvFormat" in angle_format and "srvFormat" in angle_format and not channels_different and len(angle_format['channels']) == 4: + return angle_format["glInternalFormat"] if "glInternalFormat" in angle_format else internal_format + + b = int(math.ceil(float(max_component_bits) / 8) * 8) + + # Depth formats need special handling, since combined depth/stencil formats don't have a clearly + # defined component type. + if angle_format['channels'].find('d') >= 0: + if b == 24 or b == 32: + return 'GL_RGBA32F' + if b == 16: + return 'GL_RGBA16_EXT' + + if b == 24: + raise ValueError('unexpected 24-bit format when determining swizzleformat for format: ' + internal_format) + + if 'componentType' not in angle_format: + raise ValueError('no component type information for determining swizzleformat for format: ' + internal_format) + + component_type = angle_format['componentType'] + + swizzle = "GL_RGBA" + str(b) + + if component_type == 'uint': + swizzle += "I" + elif component_type == 'int': + swizzle += "I" + elif component_type == 'unorm': + if (b == 16): + swizzle += "_EXT" + elif component_type == 'snorm': + swizzle += "_SNORM" + if (b == 16): + swizzle += "_EXT" + elif component_type == 'float': + swizzle += "F" + if (b == 16): + swizzle += "_EXT" + else: + raise ValueError('could not determine swizzleformat based on componentType for format: ' + internal_format) + + return swizzle + +def get_blit_srv_format(angle_format): + if 'channels' not in angle_format: + return 'DXGI_FORMAT_UNKNOWN' + if 'r' in angle_format['channels'] and angle_format['componentType'] in ['int', 'uint']: + return angle_format['rtvFormat'] + + return angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN" + + +format_entry_template = """{space}{{ +{space} static constexpr Format info({internalFormat}, +{space} angle::Format::ID::{formatName}, +{space} {texFormat}, +{space} {srvFormat}, +{space} {rtvFormat}, +{space} {dsvFormat}, +{space} {blitSRVFormat}, +{space} {swizzleFormat}, +{space} {initializer}); +{space} return info; +{space}}} +""" + +split_format_entry_template = """{space} {condition} +{space} {{ +{space} static constexpr Format info({internalFormat}, +{space} angle::Format::ID::{formatName}, +{space} {texFormat}, +{space} {srvFormat}, +{space} {rtvFormat}, +{space} {dsvFormat}, +{space} {blitSRVFormat}, +{space} {swizzleFormat}, +{space} {initializer}); +{space} return info; +{space} }} +""" + +def json_to_table_data(internal_format, format_name, prefix, json): + + table_data = "" + + parsed = { + "space": " ", + "internalFormat": internal_format, + "formatName": format_name, + "texFormat": "DXGI_FORMAT_UNKNOWN", + "srvFormat": "DXGI_FORMAT_UNKNOWN", + "rtvFormat": "DXGI_FORMAT_UNKNOWN", + "dsvFormat": "DXGI_FORMAT_UNKNOWN", + "condition": prefix, + } + + for k, v in json.iteritems(): + parsed[k] = v + + # Derived values. + parsed["blitSRVFormat"] = get_blit_srv_format(parsed) + parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed) + parsed["initializer"] = get_internal_format_initializer(internal_format, json) + + if len(prefix) > 0: + return split_format_entry_template.format(**parsed) + else: + return format_entry_template.format(**parsed) + +def parse_json_angle_format_case(format_name, angle_format, json_data): + supported_case = {} + unsupported_case = {} + support_test = None + fallback = None + + for k, v in angle_format.iteritems(): + if k == "FL10Plus": + assert support_test is None + support_test = "OnlyFL10Plus(deviceCaps)" + for k2, v2 in v.iteritems(): + supported_case[k2] = v2 + elif k == "FL9_3": + split = True + for k2, v2 in v.iteritems(): + unsupported_case[k2] = v2 + elif k == "supportTest": + assert support_test is None + support_test = v + elif k == "fallbackFormat": + fallback = v + else: + supported_case[k] = v + unsupported_case[k] = v + + if fallback != None: + unsupported_case, _, _ = parse_json_angle_format_case( + fallback, json_data[fallback], json_data) + unsupported_case["formatName"] = fallback + + if support_test != None: + return supported_case, unsupported_case, support_test + else: + return supported_case, None, None + +def parse_json_into_switch_angle_format_string(json_map, json_data): + table_data = '' + + for internal_format, format_name in sorted(json_map.iteritems()): + + if format_name not in json_data: + continue + + angle_format = json_data[format_name] + + supported_case, unsupported_case, support_test = parse_json_angle_format_case( + format_name, angle_format, json_data) + + table_data += ' case ' + internal_format + ':\n' + + if support_test != None: + table_data += " {\n" + table_data += json_to_table_data(internal_format, format_name, "if (" + support_test + ")", supported_case) + table_data += json_to_table_data(internal_format, format_name, "else", unsupported_case) + table_data += " }\n" + else: + table_data += json_to_table_data(internal_format, format_name, "", supported_case) + + return table_data + +def reject_duplicate_keys(pairs): + found_keys = {} + for key, value in pairs: + if key in found_keys: + raise ValueError("duplicate key: %r" % (key,)) + else: + found_keys[key] = value + return found_keys + +json_map = angle_format.load_with_override(os.path.abspath('texture_format_map.json')) +data_source_name = 'texture_format_data.json' + +with open(data_source_name) as texture_format_json_file: + texture_format_data = texture_format_json_file.read() + texture_format_json_file.close() + json_data = json.loads(texture_format_data, object_pairs_hook=angle_format.reject_duplicate_keys) + + angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data) + output_cpp = template_texture_format_table_autogen_cpp.format( + script_name = sys.argv[0], + copyright_year = date.today().year, + angle_format_info_cases = angle_format_cases, + data_source_name = data_source_name) + with open('texture_format_table_autogen.cpp', 'wt') as out_file: + out_file.write(output_cpp) + out_file.close() diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp new file mode 100755 index 000000000..5bb51feca --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -0,0 +1,2096 @@ +// +// 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_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include <algorithm> + +#include "common/debug.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" +#include "libANGLE/renderer/driver_utils.h" + +namespace rx +{ + +namespace d3d11_gl +{ +namespace +{ + +// Helper functor for querying DXGI support. Saves passing the parameters repeatedly. +class DXGISupportHelper : angle::NonCopyable +{ + public: + DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel) + : mDevice(device), mFeatureLevel(featureLevel) + { + } + + bool query(DXGI_FORMAT dxgiFormat, UINT supportMask) + { + if (dxgiFormat == DXGI_FORMAT_UNKNOWN) + return false; + + auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel); + + UINT supportedBits = dxgiSupport.alwaysSupportedFlags; + + if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0) + { + UINT formatSupport; + if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport))) + { + supportedBits |= (formatSupport & supportMask); + } + else + { + // TODO(jmadill): find out why we fail this call sometimes in FL9_3 + // ERR("Error checking format support for format 0x%x", dxgiFormat); + } + } + + return ((supportedBits & supportMask) == supportMask); + } + + private: + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; +}; + +gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, + GLenum internalFormat, + ID3D11Device *device, + const Renderer11DeviceCaps &renderer11DeviceCaps) +{ + gl::TextureCaps textureCaps; + + DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + + UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; + if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) + { + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; + if (maxClientVersion > 2) + { + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } + } + + textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask); + textureCaps.filterable = + support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE); + textureCaps.renderable = + (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) || + (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)); + + DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN; + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) + { + renderFormat = formatInfo.dsvFormat; + } + else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + renderFormat = formatInfo.rtvFormat; + } + if (renderFormat != DXGI_FORMAT_UNKNOWN && + support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + { + // Assume 1x + textureCaps.sampleCounts.insert(1); + + for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; + sampleCount *= 2) + { + UINT qualityCount = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount, + &qualityCount))) + { + // Assume we always support lower sample counts + if (qualityCount == 0) + { + break; + } + textureCaps.sampleCounts.insert(sampleCount); + } + } + } + + return textureCaps; +} + +bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_MAX_MAXANISOTROPY; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return 16; + + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: + UNREACHABLE(); + return 0; + } +} + +bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return true; + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateQuery + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return true; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be + // instanced. + // D3D9 has a similar restriction, where stream 0 must not be instanced. + // This restriction can be worked around by remapping any non-instanced slot to slot + // 0. + // This works because HLSL uses shader semantics to match the vertex inputs to the + // elements in the input layout, rather than the slots. + // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 + // doesn't support OpenGL ES 3.0 + case D3D_FEATURE_LEVEL_9_3: + return true; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that + // shader model + // ps_2_x is required for the ddx (and other derivative functions). + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that + // feature level + // 9.3 supports shader model ps_2_x. + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } +} + +size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; + + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum + // texture sizes + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since + // that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, + "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, + "Unexpected D3D11 constant value."); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return std::numeric_limits<GLint>::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since + // that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return std::numeric_limits<GLint>::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; + case D3D_FEATURE_LEVEL_10_0: + return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; + + // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + // "Max Input Slots" + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 16; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::VSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel); + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // According to The OpenGL ES Shading Language specifications + // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21) + // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord) + // which are statically used in the shader should be included in the variable packing + // algorithm. + // Therefore, we should not reserve output vectors for them. + + switch (featureLevel) + { + // We must reserve one output vector for dx_Position. + // We also reserve one for gl_Position, which we unconditionally output on Feature + // Levels 10_0+, + // even if it's unused in the shader (e.g. for transform feedback). TODO: This could + // be improved. + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 2; + + // Just reserve dx_Position on Feature Level 9, since we don't ever need to output + // gl_Position. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 1; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, + "Unexpected D3D11 constant value."); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 8 - GetReservedVertexOutputVectors(featureLevel); + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // Vertex textures not supported on D3D11 Feature Level 9 according to + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::PSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel); + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: + return 8 - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 8 - GetReservedVertexOutputVectors(featureLevel); + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::PSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 16; + + default: + UNREACHABLE(); + return 0; + } +} + +int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +{ + // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum + // size of + // any buffer that could be allocated. + + const size_t bytesPerComponent = 4 * sizeof(float); + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx + // remarks section + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 4096 * bytesPerComponent; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_SO_BUFFER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return GetMaximumVertexOutputVectors(featureLevel) * 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return GetMaximumStreamOutputInterleavedComponents(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); + + // D3D 10 and 10.1 only allow one output per output slot if an output slot other + // than zero is used. + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; + } +} + +} // anonymous namespace + +unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 0; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale + + default: + UNREACHABLE(); + return 0; + } +} + +unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 0; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 3; + + default: + UNREACHABLE(); + return 0; + } +} + +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + return 3; + + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 2; + + default: + UNREACHABLE(); + return 0; + } +} + +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations) +{ + GLuint maxSamples = 0; + D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + // GL core feature limits + // Reserve MAX_UINT for D3D11's primitive restart. + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1); + caps->max3DTextureSize = static_cast<GLuint>(GetMaximum3DTextureSize(featureLevel)); + caps->max2DTextureSize = static_cast<GLuint>(GetMaximum2DTextureSize(featureLevel)); + caps->maxCubeMapTextureSize = static_cast<GLuint>(GetMaximumCubeMapTextureSize(featureLevel)); + caps->maxArrayTextureLayers = static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)); + + // Unimplemented, set to minimum required + caps->maxLODBias = 2.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Maximum draw buffers and color attachments are the same, max color attachments could eventually be + // increased to 16 + caps->maxDrawBuffers = static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel)); + caps->maxColorAttachments = + static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel)); + + // D3D11 has the same limit for viewport width and height + caps->maxViewportWidth = static_cast<GLuint>(GetMaximumViewportSize(featureLevel)); + caps->maxViewportHeight = caps->maxViewportWidth; + + // Choose a reasonable maximum, enforced in the shader. + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = 1024.0f; + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits + caps->maxElementsIndices = static_cast<GLuint>(GetMaximumDrawIndexedIndexCount(featureLevel)); + caps->maxElementsVertices = static_cast<GLuint>(GetMaximumDrawVertexCount(featureLevel)); + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // 32-bit integers are natively supported + caps->vertexHighpInt.setTwosComplementInt(32); + caps->vertexMediumpInt.setTwosComplementInt(32); + caps->vertexLowpInt.setTwosComplementInt(32); + caps->fragmentHighpInt.setTwosComplementInt(32); + caps->fragmentMediumpInt.setTwosComplementInt(32); + caps->fragmentLowpInt.setTwosComplementInt(32); + + // We do not wait for server fence objects internally, so report a max timeout of zero. + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = static_cast<GLuint>(GetMaximumVertexInputSlots(featureLevel)); + caps->maxVertexUniformComponents = + static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel)) * 4; + caps->maxVertexUniformVectors = + static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel)); + caps->maxVertexUniformBlocks = static_cast<GLuint>(GetMaximumVertexUniformBlocks(featureLevel)); + caps->maxVertexOutputComponents = + static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4; + caps->maxVertexTextureImageUnits = + static_cast<GLuint>(GetMaximumVertexTextureUnits(featureLevel)); + + // Fragment shader limits + caps->maxFragmentUniformComponents = + static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)) * 4; + caps->maxFragmentUniformVectors = + static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)); + caps->maxFragmentUniformBlocks = + static_cast<GLuint>(GetMaximumPixelUniformBlocks(featureLevel)); + caps->maxFragmentInputComponents = + static_cast<GLuint>(GetMaximumPixelInputVectors(featureLevel)) * 4; + caps->maxTextureImageUnits = static_cast<GLuint>(GetMaximumPixelTextureUnits(featureLevel)); + caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); + caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); + + // Aggregate shader limits + caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + + // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each. + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx + // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however + // we still keep the same alignment as 11.1 for consistency. + caps->uniformBufferOffsetAlignment = 256; + + caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) + + static_cast<GLint64>(caps->maxVertexUniformComponents); + caps->maxCombinedFragmentUniformComponents = (static_cast<GLint64>(caps->maxFragmentUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) + + static_cast<GLint64>(caps->maxFragmentUniformComponents); + caps->maxVaryingComponents = + static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4; + caps->maxVaryingVectors = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)); + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = + static_cast<GLuint>(GetMaximumStreamOutputInterleavedComponents(featureLevel)); + caps->maxTransformFeedbackSeparateAttributes = + static_cast<GLuint>(GetMaximumStreamOutputBuffers(featureLevel)); + caps->maxTransformFeedbackSeparateComponents = + static_cast<GLuint>(GetMaximumStreamOutputSeparateComponents(featureLevel)); + + // Multisample limits + caps->maxSamples = maxSamples; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->timerQuery = false; // Unimplemented + extensions->disjointTimerQuery = true; + extensions->queryCounterBitsTimeElapsed = 64; + extensions->queryCounterBitsTimestamp = + 0; // Timestamps cannot be supported due to D3D11 limitations + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); + extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); + extensions->fragDepth = true; + extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->discardFramebuffer = true; + extensions->translatedShaderSource = true; + extensions->fboRenderMipmap = false; + extensions->debugMarker = true; + extensions->eglImage = true; + extensions->eglImageExternal = true; + extensions->eglImageExternalEssl3 = true; + extensions->eglStreamConsumerExternal = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->lossyETCDecode = true; + extensions->syncQuery = GetEventQuerySupport(featureLevel); + extensions->copyTexture = true; + extensions->copyCompressedTexture = true; + + // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing. + // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing. + limitations->noFrontFacingSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage + limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require + // additional + // pre-validation of the shader at compile time to produce a better error message. + limitations->shadersRequireIndexedLoopValidation = + (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil + // state. + limitations->noSeparateStencilRefsAndMasks = true; + + // D3D11 cannot support constant color and alpha blend funcs together + limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true; + +#ifdef ANGLE_ENABLE_WINDOWS_STORE + // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era devices. + // We should prevent developers from doing this on ALL Windows Store devices. This will maintain consistency across all Windows devices. + // We allow non-zero divisors on attribute zero if the Client Version >= 3, since devices affected by this issue don't support ES3+. + limitations->attributeZeroRequiresZeroDivisorInEXT = true; +#endif +} + +} // namespace d3d11_gl + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: + d3dBlend = D3D11_BLEND_ZERO; + break; + case GL_ONE: + d3dBlend = D3D11_BLEND_ONE; + break; + case GL_SRC_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); + break; + case GL_ONE_MINUS_SRC_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); + break; + case GL_DST_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); + break; + case GL_ONE_MINUS_DST_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); + break; + case GL_SRC_ALPHA: + d3dBlend = D3D11_BLEND_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; + break; + case GL_DST_ALPHA: + d3dBlend = D3D11_BLEND_DEST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; + break; + case GL_CONSTANT_COLOR: + d3dBlend = D3D11_BLEND_BLEND_FACTOR; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; + break; + case GL_CONSTANT_ALPHA: + d3dBlend = D3D11_BLEND_BLEND_FACTOR; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; + break; + case GL_SRC_ALPHA_SATURATE: + d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; + break; + default: + UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: + d3dBlendOp = D3D11_BLEND_OP_ADD; + break; + case GL_FUNC_SUBTRACT: + d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; + break; + case GL_FUNC_REVERSE_SUBTRACT: + d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; + break; + case GL_MIN: + d3dBlendOp = D3D11_BLEND_OP_MIN; + break; + case GL_MAX: + d3dBlendOp = D3D11_BLEND_OP_MAX; + break; + default: + UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case GL_FRONT: + cull = D3D11_CULL_FRONT; + break; + case GL_BACK: + cull = D3D11_CULL_BACK; + break; + case GL_FRONT_AND_BACK: + cull = D3D11_CULL_NONE; + break; + default: + UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: + d3dComp = D3D11_COMPARISON_NEVER; + break; + case GL_ALWAYS: + d3dComp = D3D11_COMPARISON_ALWAYS; + break; + case GL_LESS: + d3dComp = D3D11_COMPARISON_LESS; + break; + case GL_LEQUAL: + d3dComp = D3D11_COMPARISON_LESS_EQUAL; + break; + case GL_EQUAL: + d3dComp = D3D11_COMPARISON_EQUAL; + break; + case GL_GREATER: + d3dComp = D3D11_COMPARISON_GREATER; + break; + case GL_GEQUAL: + d3dComp = D3D11_COMPARISON_GREATER_EQUAL; + break; + case GL_NOTEQUAL: + d3dComp = D3D11_COMPARISON_NOT_EQUAL; + break; + default: + UNREACHABLE(); + } + + return d3dComp; +} + +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} + +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast<UINT8>(stencilmask); +} + +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: + d3dStencilOp = D3D11_STENCIL_OP_ZERO; + break; + case GL_KEEP: + d3dStencilOp = D3D11_STENCIL_OP_KEEP; + break; + case GL_REPLACE: + d3dStencilOp = D3D11_STENCIL_OP_REPLACE; + break; + case GL_INCR: + d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; + break; + case GL_DECR: + d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; + break; + case GL_INVERT: + d3dStencilOp = D3D11_STENCIL_OP_INVERT; + break; + case GL_INCR_WRAP: + d3dStencilOp = D3D11_STENCIL_OP_INCR; + break; + case GL_DECR_WRAP: + d3dStencilOp = D3D11_STENCIL_OP_DECR; + break; + default: + UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3D11_FILTER ConvertFilter(GLenum minFilter, + GLenum magFilter, + float maxAnisotropy, + GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; + + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison)); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_NEAREST_MIPMAP_NEAREST: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_LINEAR; + break; + default: + UNREACHABLE(); + } + + D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: + dxMag = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR: + dxMag = D3D11_FILTER_TYPE_LINEAR; + break; + default: + UNREACHABLE(); + } + + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, + static_cast<D3D11_COMPARISON_FUNC>(comparison)); + } +} + +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: + return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: + return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: + return D3D11_TEXTURE_ADDRESS_MIRROR; + default: + UNREACHABLE(); + } + + return D3D11_TEXTURE_ADDRESS_WRAP; +} + +UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel) +{ + return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel))); +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + return D3D11_QUERY_OCCLUSION; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return D3D11_QUERY_SO_STATISTICS; + case GL_TIME_ELAPSED_EXT: + // Two internal queries are also created for begin/end timestamps + return D3D11_QUERY_TIMESTAMP_DISJOINT; + case GL_COMMANDS_COMPLETED_CHROMIUM: + return D3D11_QUERY_EVENT; + default: + UNREACHABLE(); + return D3D11_QUERY_EVENT; + } +} + +} // namespace gl_d3d11 + +namespace d3d11 +{ + +ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) +{ + // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value, + // since it is difficult to tell Software and Reference devices apart + + IDXGIDevice *dxgiDevice = nullptr; + IDXGIAdapter *dxgiAdapter = nullptr; + IDXGIAdapter2 *dxgiAdapter2 = nullptr; + + ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN; + + HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice); + if (SUCCEEDED(hr)) + { + hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter); + if (SUCCEEDED(hr)) + { + std::wstring adapterString; + HRESULT adapter2hr = + dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2); + if (SUCCEEDED(adapter2hr)) + { + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" + // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the + // actual hardware values if possible. + DXGI_ADAPTER_DESC2 adapterDesc2; + dxgiAdapter2->GetDesc2(&adapterDesc2); + adapterString = std::wstring(adapterDesc2.Description); + } + else + { + DXGI_ADAPTER_DESC adapterDesc; + dxgiAdapter->GetDesc(&adapterDesc); + adapterString = std::wstring(adapterDesc.Description); + } + + // Both Reference and Software adapters will be 'Software Adapter' + const bool isSoftwareDevice = + (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos); + const bool isNullDevice = (adapterString == L""); + const bool isWARPDevice = + (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos); + + if (isSoftwareDevice || isNullDevice) + { + ASSERT(!isWARPDevice); + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL; + } + else if (isWARPDevice) + { + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP; + } + else + { + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE; + } + } + } + + SafeRelease(dxgiDevice); + SafeRelease(dxgiAdapter); + SafeRelease(dxgiAdapter2); + + return retDeviceType; +} + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) || + *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight)) + { + while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +void GenerateInitialTextureData(GLint internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + GLuint width, + GLuint height, + GLuint depth, + GLuint mipLevels, + std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, + std::vector<std::vector<BYTE>> *outData) +{ + const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); + + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat); + + outSubresourceData->resize(mipLevels); + outData->resize(mipLevels); + + for (unsigned int i = 0; i < mipLevels; i++) + { + unsigned int mipWidth = std::max(width >> i, 1U); + unsigned int mipHeight = std::max(height >> i, 1U); + unsigned int mipDepth = std::max(depth >> i, 1U); + + unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth; + unsigned int imageSize = rowWidth * height; + + outData->at(i).resize(rowWidth * mipHeight * mipDepth); + d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + + outSubresourceData->at(i).pSysMem = outData->at(i).data(); + outSubresourceData->at(i).SysMemPitch = rowWidth; + outSubresourceData->at(i).SysMemSlicePitch = imageSize; + } +} + +UINT GetPrimitiveRestartIndex() +{ + return std::numeric_limits<UINT>::max(); +} + +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) +{ + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; +} + +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s) +{ + vertex->x = x; + vertex->y = y; + vertex->l = layer; + vertex->u = u; + vertex->v = v; + vertex->s = s; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + UINT existingDataSize = 0; + resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr); + // Don't check the HRESULT- if it failed then that probably just means that no private data + // exists yet + + if (existingDataSize > 0) + { + // In some cases, ANGLE will try to apply two names to one object, which causes + // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects + // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize + // these calls and return the same object both times. + static const char *multipleNamesUsed = "Multiple names set by ANGLE"; + + // Remove the existing name + HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr); + if (FAILED(hr)) + { + return hr; + } + + // Apply the new name + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast<unsigned int>(strlen(multipleNamesUsed)), + multipleNamesUsed); + } + else + { + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast<unsigned int>(strlen(name)), name); + } +#else + return S_OK; +#endif +} + +LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, + size_t inputDescLen, + const BYTE *byteCode, + size_t byteCodeLen, + const char *debugName) + : mInputDesc(inputDescLen), + mByteCodeLen(byteCodeLen), + mByteCode(byteCode), + mDebugName(debugName) +{ + memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); +} + +ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + + if (mResource == nullptr) + { + HRESULT result = + device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()), + mByteCode, mByteCodeLen, &mResource); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mResource, mDebugName); + } + + return mResource; +} + +LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName) + : mDesc(desc), mDebugName(debugName) +{ +} + +ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + + if (mResource == nullptr) + { + HRESULT result = device->CreateBlendState(&mDesc, &mResource); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mResource, mDebugName); + } + + return mResource; +} + +WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, + const DXGI_ADAPTER_DESC &adapterDesc) +{ + bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + WorkaroundsD3D workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = true; + workarounds.zeroMaxLodWorkaround = is9_3; + workarounds.useInstancedPointSpriteEmulation = is9_3; + + // TODO(jmadill): Narrow problematic driver range. + if (IsNvidia(adapterDesc.VendorId)) + { + if (deviceCaps.driverVersion.valid()) + { + WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart); + WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart); + + // Disable the workaround to fix a second driver bug on newer NVIDIA. + workarounds.depthStencilBlitExtraCopy = (part1 <= 13u && part2 < 6881); + } + else + { + workarounds.depthStencilBlitExtraCopy = true; + } + } + + // TODO(jmadill): Disable workaround when we have a fixed compiler DLL. + workarounds.expandIntegerPowExpressions = true; + + workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId); + workarounds.getDimensionsIgnoresBaseLevel = IsNvidia(adapterDesc.VendorId); + + workarounds.preAddTexelFetchOffsets = IsIntel(adapterDesc.VendorId); + workarounds.disableB5G6R5Support = IsIntel(adapterDesc.VendorId); + workarounds.rewriteUnaryMinusOperator = + IsIntel(adapterDesc.VendorId) && + (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId)); + workarounds.emulateIsnanFloat = + IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId); + workarounds.callClearTwice = + IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId); + + // TODO(jmadill): Disable when we have a fixed driver version. + workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId); + + // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a + // depth stencil texture. This is not allowed until feature level 10.1 but since it is not + // possible to support ES3 on these devices, there is no need for the workaround to begin with + // (anglebug.com/1572). + if (deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1) + { + workarounds.emulateTinyStencilTextures = false; + } + + workarounds.useSystemMemoryForConstantBuffers = IsIntel(adapterDesc.VendorId); + + return workarounds; +} + +void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth) +{ + constantBufferDescription->ByteWidth = static_cast<UINT>(byteWidth); + constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription->MiscFlags = 0; + constantBufferDescription->StructureByteStride = 0; +} + +} // namespace d3d11 + +TextureHelper11::TextureHelper11() + : mTextureType(GL_NONE), + mFormat(DXGI_FORMAT_UNKNOWN), + mFormatSet(nullptr), + mSampleCount(0), + mTexture2D(nullptr), + mTexture3D(nullptr) +{ +} + +TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) + : mTextureType(toCopy.mTextureType), + mExtents(toCopy.mExtents), + mFormat(toCopy.mFormat), + mFormatSet(toCopy.mFormatSet), + mSampleCount(toCopy.mSampleCount), + mTexture2D(toCopy.mTexture2D), + mTexture3D(toCopy.mTexture3D) +{ + toCopy.reset(); +} + +// static +TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource, + const d3d11::Format &formatSet) +{ + TextureHelper11 newHelper; + newHelper.mFormatSet = &formatSet; + newHelper.mTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(genericResource); + newHelper.mTexture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(genericResource); + newHelper.mTextureType = newHelper.mTexture2D ? GL_TEXTURE_2D : GL_TEXTURE_3D; + newHelper.initDesc(); + return newHelper; +} + +// static +TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn, + const d3d11::Format &formatSet) +{ + TextureHelper11 newHelper; + newHelper.mFormatSet = &formatSet; + newHelper.mTexture2D = texToOwn; + newHelper.mTextureType = GL_TEXTURE_2D; + newHelper.initDesc(); + return newHelper; +} + +// static +TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn, + const d3d11::Format &formatSet) +{ + TextureHelper11 newHelper; + newHelper.mFormatSet = &formatSet; + newHelper.mTexture3D = texToOwn; + newHelper.mTextureType = GL_TEXTURE_3D; + newHelper.initDesc(); + return newHelper; +} + +void TextureHelper11::initDesc() +{ + if (mTextureType == GL_TEXTURE_2D) + { + ASSERT(!mTexture3D); + D3D11_TEXTURE2D_DESC desc2D; + mTexture2D->GetDesc(&desc2D); + + mExtents.width = static_cast<int>(desc2D.Width); + mExtents.height = static_cast<int>(desc2D.Height); + mExtents.depth = 1; + mFormat = desc2D.Format; + mSampleCount = desc2D.SampleDesc.Count; + } + else + { + ASSERT(mTexture3D && mTextureType == GL_TEXTURE_3D); + D3D11_TEXTURE3D_DESC desc3D; + mTexture3D->GetDesc(&desc3D); + + mExtents.width = static_cast<int>(desc3D.Width); + mExtents.height = static_cast<int>(desc3D.Height); + mExtents.depth = static_cast<int>(desc3D.Depth); + mFormat = desc3D.Format; + mSampleCount = 1; + } + ASSERT(mFormatSet && mFormat == mFormatSet->texFormat); +} + +TextureHelper11::~TextureHelper11() +{ + SafeRelease(mTexture2D); + SafeRelease(mTexture3D); +} + +ID3D11Resource *TextureHelper11::getResource() const +{ + return mTexture2D ? static_cast<ID3D11Resource *>(mTexture2D) + : static_cast<ID3D11Resource *>(mTexture3D); +} + +TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture) +{ + SafeRelease(mTexture2D); + SafeRelease(mTexture3D); + + mTextureType = texture.mTextureType; + mExtents = texture.mExtents; + mFormat = texture.mFormat; + mFormatSet = texture.mFormatSet; + mSampleCount = texture.mSampleCount; + mTexture2D = texture.mTexture2D; + mTexture3D = texture.mTexture3D; + texture.reset(); + return *this; +} + +void TextureHelper11::reset() +{ + mTextureType = GL_NONE; + mExtents = gl::Extents(); + mFormat = DXGI_FORMAT_UNKNOWN; + mFormatSet = nullptr; + mSampleCount = 0; + mTexture2D = nullptr; + mTexture3D = nullptr; +} + +bool TextureHelper11::valid() const +{ + return (mTextureType != GL_NONE); +} + +gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess, + ID3D11Device *device) +{ + if (textureType == GL_TEXTURE_2D) + { + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = formatSet.texFormat; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + if (readAndWriteAccess == StagingAccess::READ_WRITE) + { + stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE; + } + + ID3D11Texture2D *stagingTex = nullptr; + HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTex); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", + result); + } + + return TextureHelper11::MakeAndPossess2D(stagingTex, formatSet); + } + ASSERT(textureType == GL_TEXTURE_3D); + + D3D11_TEXTURE3D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.Depth = 1; + stagingDesc.MipLevels = 1; + stagingDesc.Format = formatSet.texFormat; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture3D *stagingTex = nullptr; + HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", + result); + } + + return TextureHelper11::MakeAndPossess3D(stagingTex, formatSet); +} + +bool UsePresentPathFast(const Renderer11 *renderer, + const gl::FramebufferAttachment *framebufferAttachment) +{ + if (framebufferAttachment == nullptr) + { + return false; + } + + return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && + renderer->presentPathFastEnabled()); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h new file mode 100755 index 000000000..463571cf9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -0,0 +1,419 @@ +// +// 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_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ + +#include <array> +#include <functional> +#include <vector> + +#include "common/Color.h" + +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +class Renderer11; +class RenderTarget11; +struct WorkaroundsD3D; +struct Renderer11DeviceCaps; + +using RenderTargetArray = std::array<RenderTarget11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>; +using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>; + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); +UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); +UINT8 ConvertStencilMask(GLuint stencilmask); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); +UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel); + +D3D11_QUERY ConvertQueryType(GLenum queryType); + +} // namespace gl_d3d11 + +namespace d3d11_gl +{ + +unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel); + +unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel); + +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations); + +} // namespace d3d11_gl + +namespace d3d11 +{ + +enum ANGLED3D11DeviceType +{ + ANGLE_D3D11_DEVICE_TYPE_UNKNOWN, + ANGLE_D3D11_DEVICE_TYPE_HARDWARE, + ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL, + ANGLE_D3D11_DEVICE_TYPE_WARP, +}; + +ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device); + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +void GenerateInitialTextureData(GLint internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + GLuint width, + GLuint height, + GLuint depth, + GLuint mipLevels, + std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, + std::vector<std::vector<BYTE>> *outData); + +UINT GetPrimitiveRestartIndex(); + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionLayerTexCoord3DVertex +{ + float x, y; + unsigned int l; + float u, v, s; +}; +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s); + +template <typename T> +struct PositionDepthColorVertex +{ + float x, y, z; + T r, g, b, a; +}; + +template <typename T> +void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, float y, float z, + const gl::Color<T> &color) +{ + vertex->x = x; + vertex->y = y; + vertex->z = z; + vertex->r = color.red; + vertex->g = color.green; + vertex->b = color.blue; + vertex->a = color.alpha; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template <typename outType> +outType* DynamicCastComObject(IUnknown* object) +{ + outType *outObject = NULL; + HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject)); + if (SUCCEEDED(result)) + { + return outObject; + } + else + { + SafeRelease(outObject); + return NULL; + } +} + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + return true; + default: + return false; + } +} + +inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) +{ + ID3D11VertexShader *vs = nullptr; + HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + SetDebugName(vs, name); + return vs; + } + return nullptr; +} + +template <unsigned int N> +ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompileVS(device, byteCode, N, name); +} + +inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) +{ + ID3D11GeometryShader *gs = nullptr; + HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + SetDebugName(gs, name); + return gs; + } + return nullptr; +} + +template <unsigned int N> +ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompileGS(device, byteCode, N, name); +} + +inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) +{ + ID3D11PixelShader *ps = nullptr; + HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + SetDebugName(ps, name); + return ps; + } + return nullptr; +} + +template <unsigned int N> +ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompilePS(device, byteCode, N, name); +} + +template <typename ResourceType> +class LazyResource : public angle::NonCopyable +{ + public: + LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {} + virtual ~LazyResource() { release(); } + + virtual ResourceType *resolve(ID3D11Device *device) = 0; + void release() { SafeRelease(mResource); } + + protected: + void checkAssociatedDevice(ID3D11Device *device); + + ResourceType *mResource; + ID3D11Device *mAssociatedDevice; +}; + +template <typename ResourceType> +void LazyResource<ResourceType>::checkAssociatedDevice(ID3D11Device *device) +{ + ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice); + mAssociatedDevice = device; +} + +template <typename D3D11ShaderType> +class LazyShader final : public LazyResource<D3D11ShaderType> +{ + public: + // All parameters must be constexpr. Not supported in VS2013. + LazyShader(const BYTE *byteCode, + size_t byteCodeSize, + const char *name) + : mByteCode(byteCode), + mByteCodeSize(byteCodeSize), + mName(name) + { + } + + D3D11ShaderType *resolve(ID3D11Device *device) override; + + private: + const BYTE *mByteCode; + size_t mByteCodeSize; + const char *mName; +}; + +template <> +inline ID3D11VertexShader *LazyShader<ID3D11VertexShader>::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompileVS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; +} + +template <> +inline ID3D11GeometryShader *LazyShader<ID3D11GeometryShader>::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompileGS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; +} + +template <> +inline ID3D11PixelShader *LazyShader<ID3D11PixelShader>::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompilePS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; +} + +class LazyInputLayout final : public LazyResource<ID3D11InputLayout> +{ + public: + LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, + size_t inputDescLen, + const BYTE *byteCode, + size_t byteCodeLen, + const char *debugName); + + ID3D11InputLayout *resolve(ID3D11Device *device) override; + + private: + std::vector<D3D11_INPUT_ELEMENT_DESC> mInputDesc; + size_t mByteCodeLen; + const BYTE *mByteCode; + const char *mDebugName; +}; + +class LazyBlendState final : public LazyResource<ID3D11BlendState> +{ + public: + LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName); + + ID3D11BlendState *resolve(ID3D11Device *device) override; + + private: + D3D11_BLEND_DESC mDesc; + const char *mDebugName; +}; + +// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to +// represent an entire buffer. +template <class T> +void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +{ + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + memcpy(mappedResource.pData, &value, sizeof(T)); + context->Unmap(constantBuffer, 0); + } +} + +WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, + const DXGI_ADAPTER_DESC &adapterDesc); + +enum ReservedConstantBufferSlot +{ + RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0, + RESERVED_CONSTANT_BUFFER_SLOT_DRIVER = 1, + + RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2 +}; + +void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth); +} // namespace d3d11 + +// A helper class which wraps a 2D or 3D texture. +class TextureHelper11 : angle::NonCopyable +{ + public: + TextureHelper11(); + TextureHelper11(TextureHelper11 &&toCopy); + ~TextureHelper11(); + TextureHelper11 &operator=(TextureHelper11 &&texture); + + static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource, + const d3d11::Format &formatSet); + static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn, + const d3d11::Format &formatSet); + static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn, + const d3d11::Format &formatSet); + + GLenum getTextureType() const { return mTextureType; } + gl::Extents getExtents() const { return mExtents; } + DXGI_FORMAT getFormat() const { return mFormat; } + const d3d11::Format &getFormatSet() const { return *mFormatSet; } + int getSampleCount() const { return mSampleCount; } + ID3D11Texture2D *getTexture2D() const { return mTexture2D; } + ID3D11Texture3D *getTexture3D() const { return mTexture3D; } + ID3D11Resource *getResource() const; + bool valid() const; + + private: + void reset(); + void initDesc(); + + GLenum mTextureType; + gl::Extents mExtents; + DXGI_FORMAT mFormat; + const d3d11::Format *mFormatSet; + int mSampleCount; + ID3D11Texture2D *mTexture2D; + ID3D11Texture3D *mTexture3D; +}; + +enum class StagingAccess +{ + READ, + READ_WRITE, +}; + +gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess, + ID3D11Device *device); + +bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl new file mode 100755 index 000000000..c43734f6a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl @@ -0,0 +1,77 @@ +Buffer<float4> Buffer4F : register(t0); +Buffer<int4> Buffer4I : register(t0); +Buffer<uint4> Buffer4UI : register(t0); + +struct VS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : LAYER; +}; + +struct GS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : SV_RenderTargetArrayIndex; +}; + +cbuffer BufferCopyParams : register(b0) +{ + uint FirstPixelOffset; + uint PixelsPerRow; + uint RowStride; + uint RowsPerSlice; + float2 PositionOffset; + float2 PositionScale; + int2 TexLocationOffset; + int2 TexLocationScale; + uint FirstSlice; +} + +void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) +{ + uint PixelsPerSlice = PixelsPerRow * RowsPerSlice; + uint SliceStride = RowStride * RowsPerSlice; + + uint slice = vertexID / PixelsPerSlice; + uint sliceOffset = slice * PixelsPerSlice; + uint row = (vertexID - sliceOffset) / PixelsPerRow; + uint col = vertexID - sliceOffset - (row * PixelsPerRow); + + float2 coords = float2(float(col), float(row)); + + outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); + outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; + outVertex.slice = FirstSlice + slice; +} + +void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) +{ + ComputePositionAndIndex(vertexID, outVertex); +} + +[maxvertexcount(1)] +void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream<GS_OUTPUT> outStream) +{ + GS_OUTPUT outVertex; + outVertex.position = inVertex[0].position; + outVertex.index = inVertex[0].index; + outVertex.slice = inVertex[0].slice; + outStream.Append(outVertex); +} + +float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4F.Load(inIndex); +} + +int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4I.Load(inIndex); +} + +uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4UI.Load(inIndex); +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl new file mode 100755 index 000000000..2b3e1ebe4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -0,0 +1,119 @@ +// Assume we are in SM4+, which has 8 color outputs + +void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputFloat +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +}; + +PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} + +struct PS_OutputFloat_FL9 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +}; + +PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat_FL9 outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + return outColor; +} + +void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputUint +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + uint4 color6 : SV_TARGET6; + uint4 color7 : SV_TARGET7; +}; + +PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +{ + PS_OutputUint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} + + +void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputSint +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + int4 color6 : SV_TARGET6; + int4 color7 : SV_TARGET7; +}; + +PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +{ + PS_OutputSint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl new file mode 100755 index 000000000..21024e3b7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -0,0 +1,145 @@ +Texture2D<float4> TextureF : register(t0); +Texture2D<uint4> TextureUI : register(t0); +Texture2D<int4> TextureI : register(t0); + +SamplerState Sampler : register(s0); + +void VS_Passthrough2D( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, + out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) +{ + outPosition = float4(inPosition, 0.0f, 1.0f); + outTexCoord = inTexCoord; +} + +float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH +{ + return TextureF.Sample(Sampler, inTexCoord).r; +} + +float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rgba; +} + +float4 PS_PassthroughRGBAPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return color; +} + +float4 PS_PassthroughRGBAUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return color; +} + +uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return TextureUI.Load(int3(size * inTexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return TextureI.Load(int3(size * inTexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +float4 PS_PassthroughRGBPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return color; +} + +float4 PS_PassthroughRGBUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return color; +} + +uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rrra; +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl new file mode 100755 index 000000000..c23c9032e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl @@ -0,0 +1,146 @@ +Texture3D<float4> TextureF : register(t0); +Texture3D<uint4> TextureUI : register(t0); +Texture3D<int4> TextureI : register(t0); + +SamplerState Sampler : register(s0); + +struct VS_INPUT +{ + float2 Position : POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct GS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : SV_RENDERTARGETARRAYINDEX; + float3 TexCoord : TEXCOORD; +}; + +VS_OUTPUT VS_Passthrough3D(VS_INPUT input) +{ + VS_OUTPUT output; + + output.Position = float4(input.Position, 0.0f, 1.0f); + output.Layer = input.Layer; + output.TexCoord = input.TexCoord; + + return output; +} + +[maxvertexcount(3)] +void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream<GS_OUTPUT> outputStream) +{ + GS_OUTPUT output; + + for (int i = 0; i < 3; i++) + { + output.Position = input[i].Position; + output.Layer = input[i].Layer; + output.TexCoord = input[i].TexCoord; + + outputStream.Append(output); + } +} + +float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rgba; +} + +uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return TextureI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rrra; +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl new file mode 100755 index 000000000..70df1d1b6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl @@ -0,0 +1,56 @@ +static const float2 g_Corners[6] = +{ + float2(-1.0f, 1.0f), + float2( 1.0f, -1.0f), + float2(-1.0f, -1.0f), + float2(-1.0f, 1.0f), + float2( 1.0f, 1.0f), + float2( 1.0f, -1.0f), +}; + +void VS_ResolveDepthStencil(in uint id : SV_VertexID, + out float4 position : SV_Position, + out float2 texCoord : TEXCOORD0) +{ + float2 corner = g_Corners[id]; + position = float4(corner.x, corner.y, 0.0f, 1.0f); + texCoord = float2((corner.x + 1.0f) * 0.5f, (-corner.y + 1.0f) * 0.5f); +} + +Texture2DMS<float> Depth : register(t0); +Texture2DMS<uint2> Stencil : register(t1); + +void PS_ResolveDepth(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float depth : SV_Target0) +{ + // MS samplers must use Load + uint width, height, samples; + Depth.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + depth = Depth.Load(coord, 0).r; +} + +void PS_ResolveDepthStencil(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float2 depthStencil : SV_Target0) +{ + // MS samplers must use Load + uint width, height, samples; + Depth.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + depthStencil.r = Depth.Load(coord, 0).r; + depthStencil.g = float(Stencil.Load(coord, 0).g); +} + +void PS_ResolveStencil(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float2 stencil : SV_Target0) +{ + // MS samplers must use Load + uint width, height, samples; + Stencil.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + stencil.r = 0.0f; + stencil.g = float(Stencil.Load(coord, 0).g); +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl new file mode 100755 index 000000000..505e22213 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl @@ -0,0 +1,99 @@ +Texture2D<float4> TextureF2D : register(t0); +Texture2D<uint4> TextureUI2D : register(t0); +Texture2D<int4> TextureI2D : register(t0); + +Texture3D<float4> TextureF3D : register(t0); +Texture3D<uint4> TextureUI3D : register(t0); +Texture3D<int4> TextureI3D : register(t0); + +Texture2DArray<float4> TextureF2DArray : register(t0); +Texture2DArray<uint4> TextureUI2DArray : register(t0); +Texture2DArray<int4> TextureI2DArray : register(t0); + +SamplerState Sampler : register(s0); + +cbuffer SwizzleProperties : register(b0) +{ + uint4 SwizzleIndices : packoffset(c0); +} + +float4 SwizzleLookup(in float4 sample) +{ + float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +int4 SwizzleLookup(in int4 sample) +{ + int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +uint4 SwizzleLookup(in uint4 sample) +{ + uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer))); +} + +int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} + +uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h new file mode 100755 index 000000000..71a2fec64 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h @@ -0,0 +1,165 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// LAYER 0 y 1 NONE uint y
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// SV_RenderTargetArrayIndex 0 y 1 RTINDEX uint y
+//
+gs_4_0
+dcl_input_siv v[1][0].xyzw, position
+dcl_input v[1][1].x
+dcl_input v[1][1].y
+dcl_inputprimitive point
+dcl_outputtopology pointlist
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output_siv o1.y, rendertarget_array_index
+dcl_maxout 1
+mov o0.xyzw, v[0][0].xyzw
+mov o1.x, v[0][1].x
+mov o1.y, v[0][1].y
+emit
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_GS_BufferToTexture[] =
+{
+ 68, 88, 66, 67, 79, 166,
+ 191, 97, 16, 63, 142, 167,
+ 231, 92, 119, 74, 86, 7,
+ 58, 165, 1, 0, 0, 0,
+ 212, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 0, 1,
+ 0, 0, 136, 1, 0, 0,
+ 88, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 83, 71, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 108, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 15, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 0, 0,
+ 83, 86, 95, 80, 111, 115,
+ 105, 116, 105, 111, 110, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 76, 65, 89,
+ 69, 82, 0, 171, 79, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 14,
+ 0, 0, 101, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 2, 13,
+ 0, 0, 83, 86, 95, 80,
+ 111, 115, 105, 116, 105, 111,
+ 110, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 83,
+ 86, 95, 82, 101, 110, 100,
+ 101, 114, 84, 97, 114, 103,
+ 101, 116, 65, 114, 114, 97,
+ 121, 73, 110, 100, 101, 120,
+ 0, 171, 83, 72, 68, 82,
+ 200, 0, 0, 0, 64, 0,
+ 2, 0, 50, 0, 0, 0,
+ 97, 0, 0, 5, 242, 16,
+ 32, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 95, 0, 0, 4,
+ 18, 16, 32, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 95, 0, 0, 4, 34, 16,
+ 32, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 93, 8,
+ 0, 1, 92, 8, 0, 1,
+ 103, 0, 0, 4, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 18, 32, 16, 0,
+ 1, 0, 0, 0, 103, 0,
+ 0, 4, 34, 32, 16, 0,
+ 1, 0, 0, 0, 4, 0,
+ 0, 0, 94, 0, 0, 2,
+ 1, 0, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 32, 16, 0,
+ 1, 0, 0, 0, 10, 16,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 6, 34, 32, 16, 0,
+ 1, 0, 0, 0, 26, 16,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 19, 0,
+ 0, 1, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h new file mode 100755 index 000000000..cfc0c3faa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h @@ -0,0 +1,229 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer BufferCopyParams
+// {
+//
+// uint FirstPixelOffset; // Offset: 0 Size: 4 [unused]
+// uint PixelsPerRow; // Offset: 4 Size: 4 [unused]
+// uint RowStride; // Offset: 8 Size: 4 [unused]
+// uint RowsPerSlice; // Offset: 12 Size: 4 [unused]
+// float2 PositionOffset; // Offset: 16 Size: 8 [unused]
+// float2 PositionScale; // Offset: 24 Size: 8 [unused]
+// int2 TexLocationOffset; // Offset: 32 Size: 8 [unused]
+// int2 TexLocationScale; // Offset: 40 Size: 8 [unused]
+// uint FirstSlice; // Offset: 48 Size: 4 [unused]
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4F texture float4 buf 0 1
+// BufferCopyParams cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_buffer (float,float,float,float) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4F[] =
+{
+ 68, 88, 66, 67, 176, 15,
+ 76, 123, 100, 38, 152, 23,
+ 150, 99, 165, 184, 222, 157,
+ 235, 80, 1, 0, 0, 0,
+ 252, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 2, 0, 0, 228, 2,
+ 0, 0, 24, 3, 0, 0,
+ 128, 3, 0, 0, 82, 68,
+ 69, 70, 80, 2, 0, 0,
+ 1, 0, 0, 0, 120, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 2, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 1, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 66, 117, 102, 102,
+ 101, 114, 52, 70, 0, 66,
+ 117, 102, 102, 101, 114, 67,
+ 111, 112, 121, 80, 97, 114,
+ 97, 109, 115, 0, 171, 171,
+ 101, 0, 0, 0, 9, 0,
+ 0, 0, 144, 0, 0, 0,
+ 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 1, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 140, 1, 0, 0, 4, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 153, 1, 0, 0, 8, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 163, 1, 0, 0, 12, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 176, 1, 0, 0, 16, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 192, 1,
+ 0, 0, 0, 0, 0, 0,
+ 208, 1, 0, 0, 24, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 192, 1,
+ 0, 0, 0, 0, 0, 0,
+ 222, 1, 0, 0, 32, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 240, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 40, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 240, 1,
+ 0, 0, 0, 0, 0, 0,
+ 17, 2, 0, 0, 48, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 70, 105, 114, 115, 116, 80,
+ 105, 120, 101, 108, 79, 102,
+ 102, 115, 101, 116, 0, 171,
+ 171, 171, 0, 0, 19, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 80, 105, 120, 101, 108, 115,
+ 80, 101, 114, 82, 111, 119,
+ 0, 82, 111, 119, 83, 116,
+ 114, 105, 100, 101, 0, 82,
+ 111, 119, 115, 80, 101, 114,
+ 83, 108, 105, 99, 101, 0,
+ 80, 111, 115, 105, 116, 105,
+ 111, 110, 79, 102, 102, 115,
+ 101, 116, 0, 171, 1, 0,
+ 3, 0, 1, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 80, 111, 115, 105,
+ 116, 105, 111, 110, 83, 99,
+ 97, 108, 101, 0, 84, 101,
+ 120, 76, 111, 99, 97, 116,
+ 105, 111, 110, 79, 102, 102,
+ 115, 101, 116, 0, 1, 0,
+ 2, 0, 1, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 84, 101, 120, 76,
+ 111, 99, 97, 116, 105, 111,
+ 110, 83, 99, 97, 108, 101,
+ 0, 70, 105, 114, 115, 116,
+ 83, 108, 105, 99, 101, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1,
+ 0, 0, 83, 86, 95, 80,
+ 111, 115, 105, 116, 105, 111,
+ 110, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 97, 114,
+ 103, 101, 116, 0, 171, 171,
+ 83, 72, 68, 82, 96, 0,
+ 0, 0, 64, 0, 0, 0,
+ 24, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 88, 8, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 8, 0, 3, 18, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 45, 0, 0, 7, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 6, 16, 16, 0, 1, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h new file mode 100755 index 000000000..ac952f6df --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h @@ -0,0 +1,128 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4I texture sint4 buf 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_buffer (sint,sint,sint,sint) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4I[] =
+{
+ 68, 88, 66, 67, 154, 139,
+ 95, 210, 76, 52, 228, 55,
+ 1, 175, 60, 90, 13, 234,
+ 138, 3, 1, 0, 0, 0,
+ 20, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 152, 1, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 66, 117, 102, 102, 101, 114,
+ 52, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 83, 86,
+ 95, 80, 111, 115, 105, 116,
+ 105, 111, 110, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 97, 114, 103, 101, 116, 0,
+ 171, 171, 83, 72, 68, 82,
+ 80, 0, 0, 0, 64, 0,
+ 0, 0, 20, 0, 0, 0,
+ 88, 8, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 8,
+ 0, 3, 18, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 45, 0,
+ 0, 7, 242, 32, 16, 0,
+ 0, 0, 0, 0, 6, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h new file mode 100755 index 000000000..fe7d6b27a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h @@ -0,0 +1,128 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4UI texture uint4 buf 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_buffer (uint,uint,uint,uint) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4UI[] =
+{
+ 68, 88, 66, 67, 25, 164,
+ 1, 224, 250, 219, 16, 200,
+ 83, 99, 38, 137, 116, 129,
+ 200, 39, 1, 0, 0, 0,
+ 20, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 152, 1, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 66, 117, 102, 102, 101, 114,
+ 52, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 83, 86,
+ 95, 80, 111, 115, 105, 116,
+ 105, 111, 110, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 97, 114, 103, 101, 116, 0,
+ 171, 171, 83, 72, 68, 82,
+ 80, 0, 0, 0, 64, 0,
+ 0, 0, 20, 0, 0, 0,
+ 88, 8, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 8,
+ 0, 3, 18, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 45, 0,
+ 0, 7, 242, 32, 16, 0,
+ 0, 0, 0, 0, 6, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h new file mode 100755 index 000000000..ac72f4be9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h @@ -0,0 +1,311 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer BufferCopyParams
+// {
+//
+// uint FirstPixelOffset; // Offset: 0 Size: 4
+// uint PixelsPerRow; // Offset: 4 Size: 4
+// uint RowStride; // Offset: 8 Size: 4
+// uint RowsPerSlice; // Offset: 12 Size: 4
+// float2 PositionOffset; // Offset: 16 Size: 8
+// float2 PositionScale; // Offset: 24 Size: 8
+// int2 TexLocationOffset; // Offset: 32 Size: 8 [unused]
+// int2 TexLocationScale; // Offset: 40 Size: 8 [unused]
+// uint FirstSlice; // Offset: 48 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// BufferCopyParams cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// LAYER 0 y 1 NONE uint y
+//
+vs_4_0
+dcl_constantbuffer cb0[4], immediateIndexed
+dcl_input_sgv v0.x, vertex_id
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output o1.y
+dcl_temps 2
+mov o0.zw, l(0,0,0,1.000000)
+imul null, r0.xy, cb0[0].wwww, cb0[0].yzyy
+udiv r0.z, null, v0.x, r0.x
+imad r0.x, -r0.z, r0.x, v0.x
+imad r0.y, r0.z, r0.y, cb0[0].x
+iadd o1.y, r0.z, cb0[3].x
+udiv r0.z, null, r0.x, cb0[0].y
+imad r0.x, -r0.z, cb0[0].y, r0.x
+utof r1.xy, r0.xzxx
+imad r0.y, r0.z, cb0[0].z, r0.y
+iadd o1.x, r0.x, r0.y
+mad o0.xy, cb0[1].zwzz, r1.xyxx, cb0[1].xyxx
+ret
+// Approximately 13 instruction slots used
+#endif
+
+const BYTE g_VS_BufferToTexture[] =
+{
+ 68, 88, 66, 67, 39, 207,
+ 138, 15, 42, 195, 141, 208,
+ 2, 107, 135, 197, 122, 36,
+ 114, 227, 1, 0, 0, 0,
+ 152, 5, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 2, 0, 0, 152, 2,
+ 0, 0, 12, 3, 0, 0,
+ 28, 5, 0, 0, 82, 68,
+ 69, 70, 40, 2, 0, 0,
+ 1, 0, 0, 0, 80, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 244, 1, 0, 0, 60, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 66, 117, 102, 102, 101, 114,
+ 67, 111, 112, 121, 80, 97,
+ 114, 97, 109, 115, 0, 171,
+ 171, 171, 60, 0, 0, 0,
+ 9, 0, 0, 0, 104, 0,
+ 0, 0, 64, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 64, 1, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0,
+ 0, 0, 100, 1, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0,
+ 0, 0, 113, 1, 0, 0,
+ 8, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0,
+ 0, 0, 123, 1, 0, 0,
+ 12, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0,
+ 0, 0, 136, 1, 0, 0,
+ 16, 0, 0, 0, 8, 0,
+ 0, 0, 2, 0, 0, 0,
+ 152, 1, 0, 0, 0, 0,
+ 0, 0, 168, 1, 0, 0,
+ 24, 0, 0, 0, 8, 0,
+ 0, 0, 2, 0, 0, 0,
+ 152, 1, 0, 0, 0, 0,
+ 0, 0, 182, 1, 0, 0,
+ 32, 0, 0, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0,
+ 200, 1, 0, 0, 0, 0,
+ 0, 0, 216, 1, 0, 0,
+ 40, 0, 0, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0,
+ 200, 1, 0, 0, 0, 0,
+ 0, 0, 233, 1, 0, 0,
+ 48, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0,
+ 0, 0, 70, 105, 114, 115,
+ 116, 80, 105, 120, 101, 108,
+ 79, 102, 102, 115, 101, 116,
+ 0, 171, 171, 171, 0, 0,
+ 19, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 80, 105, 120, 101,
+ 108, 115, 80, 101, 114, 82,
+ 111, 119, 0, 82, 111, 119,
+ 83, 116, 114, 105, 100, 101,
+ 0, 82, 111, 119, 115, 80,
+ 101, 114, 83, 108, 105, 99,
+ 101, 0, 80, 111, 115, 105,
+ 116, 105, 111, 110, 79, 102,
+ 102, 115, 101, 116, 0, 171,
+ 1, 0, 3, 0, 1, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 80, 111,
+ 115, 105, 116, 105, 111, 110,
+ 83, 99, 97, 108, 101, 0,
+ 84, 101, 120, 76, 111, 99,
+ 97, 116, 105, 111, 110, 79,
+ 102, 102, 115, 101, 116, 0,
+ 1, 0, 2, 0, 1, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 84, 101,
+ 120, 76, 111, 99, 97, 116,
+ 105, 111, 110, 83, 99, 97,
+ 108, 101, 0, 70, 105, 114,
+ 115, 116, 83, 108, 105, 99,
+ 101, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 83, 86,
+ 95, 86, 101, 114, 116, 101,
+ 120, 73, 68, 0, 79, 83,
+ 71, 78, 108, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 14,
+ 0, 0, 101, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 2, 13,
+ 0, 0, 83, 86, 95, 80,
+ 111, 115, 105, 116, 105, 111,
+ 110, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 76,
+ 65, 89, 69, 82, 0, 171,
+ 83, 72, 68, 82, 8, 2,
+ 0, 0, 64, 0, 1, 0,
+ 130, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 96, 0, 0, 4,
+ 18, 16, 16, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 103, 0, 0, 4, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 18, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 34, 32, 16, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 38, 0, 0, 10,
+ 0, 208, 0, 0, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 246, 143, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 150, 133, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 78, 0, 0, 8, 66, 0,
+ 16, 0, 0, 0, 0, 0,
+ 0, 208, 0, 0, 10, 16,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 35, 0, 0, 10,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 42, 0, 16, 128,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 10, 16,
+ 16, 0, 0, 0, 0, 0,
+ 35, 0, 0, 10, 34, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 0, 16, 0, 0, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 30, 0,
+ 0, 8, 34, 32, 16, 0,
+ 1, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 78, 0, 0, 9, 66, 0,
+ 16, 0, 0, 0, 0, 0,
+ 0, 208, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 35, 0, 0, 11, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 0, 16, 128, 65, 0,
+ 0, 0, 0, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 86, 0, 0, 5,
+ 50, 0, 16, 0, 1, 0,
+ 0, 0, 134, 0, 16, 0,
+ 0, 0, 0, 0, 35, 0,
+ 0, 10, 34, 0, 16, 0,
+ 0, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 26, 0, 16, 0, 0, 0,
+ 0, 0, 30, 0, 0, 7,
+ 18, 32, 16, 0, 1, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 50, 0, 0, 11, 50, 32,
+ 16, 0, 0, 0, 0, 0,
+ 230, 138, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 70, 0, 16, 0, 1, 0,
+ 0, 0, 70, 128, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 13, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 7, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h new file mode 100755 index 000000000..f8115b727 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h @@ -0,0 +1,176 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0
+ mov oC0, t0
+ mov oC1, t0
+ mov oC2, t0
+ mov oC3, t0
+
+// approximately 4 instruction slots used
+ps_4_0
+dcl_input_ps linear v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat_FL9[] =
+{
+ 68, 88, 66, 67, 36, 167,
+ 59, 21, 253, 46, 206, 132,
+ 254, 28, 18, 118, 51, 115,
+ 45, 31, 1, 0, 0, 0,
+ 236, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 168, 0, 0, 0, 72, 1,
+ 0, 0, 196, 1, 0, 0,
+ 28, 2, 0, 0, 112, 2,
+ 0, 0, 65, 111, 110, 57,
+ 104, 0, 0, 0, 104, 0,
+ 0, 0, 0, 2, 255, 255,
+ 68, 0, 0, 0, 36, 0,
+ 0, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 0, 0,
+ 36, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 1, 2,
+ 255, 255, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 176, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 1, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 2, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 3, 8, 15, 128, 0, 0,
+ 228, 176, 255, 255, 0, 0,
+ 83, 72, 68, 82, 152, 0,
+ 0, 0, 64, 0, 0, 0,
+ 38, 0, 0, 0, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 3, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 28, 0,
+ 0, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 76, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 15, 15, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 67, 79,
+ 76, 79, 82, 0, 171, 171,
+ 79, 83, 71, 78, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 8, 0, 0, 0, 104, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 104, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 15, 0, 0, 0, 104, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 15, 0, 0, 0, 104, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 3, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h new file mode 100755 index 000000000..a32268783 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h @@ -0,0 +1,195 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_TARGET 5 xyzw 5 TARGET float xyzw
+// SV_TARGET 6 xyzw 6 TARGET float xyzw
+// SV_TARGET 7 xyzw 7 TARGET float xyzw
+//
+ps_4_0
+dcl_input_ps linear v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat[] =
+{
+ 68, 88, 66, 67, 19, 30,
+ 102, 69, 166, 219, 165, 14,
+ 173, 41, 171, 133, 144, 58,
+ 14, 224, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 0, 0, 0, 8, 0,
+ 0, 0, 8, 0, 0, 0,
+ 200, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 3, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 5, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 6, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 24, 1,
+ 0, 0, 64, 0, 0, 0,
+ 70, 0, 0, 0, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 3, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 5, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 6, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 7, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h new file mode 100755 index 000000000..06d75b95e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h @@ -0,0 +1,175 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg Constant Description
+// ---------- --------------------------------------------------
+// c0 Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+ vs_2_x
+ def c1, 1, 0, 0, 0
+ dcl_texcoord v0
+ dcl_texcoord1 v1
+ add oPos.xy, v0, c0
+ mad oPos.zw, v0.z, c1.xyxy, c1.xyyx
+ mov oT0, v1
+
+// approximately 3 instruction slots used
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearFloat[] =
+{
+ 68, 88, 66, 67, 254, 253,
+ 200, 174, 22, 35, 97, 190,
+ 187, 200, 253, 161, 246, 45,
+ 67, 66, 1, 0, 0, 0,
+ 204, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 84, 1,
+ 0, 0, 208, 1, 0, 0,
+ 40, 2, 0, 0, 120, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 254, 255,
+ 104, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 0, 0,
+ 36, 0, 0, 0, 36, 0,
+ 1, 0, 36, 0, 0, 0,
+ 0, 0, 1, 2, 254, 255,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 5, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 5, 0,
+ 1, 128, 1, 0, 15, 144,
+ 2, 0, 0, 3, 0, 0,
+ 3, 192, 0, 0, 228, 144,
+ 0, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 12, 192,
+ 0, 0, 170, 144, 1, 0,
+ 68, 160, 1, 0, 20, 160,
+ 1, 0, 0, 2, 0, 0,
+ 15, 224, 1, 0, 228, 144,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 16, 16, 0, 1, 0,
+ 0, 0, 103, 0, 0, 4,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 254, 255,
+ 0, 1, 0, 0, 28, 0,
+ 0, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 72, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 7, 7, 0, 0, 65, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 15, 15, 0, 0, 80, 79,
+ 83, 73, 84, 73, 79, 78,
+ 0, 67, 79, 76, 79, 82,
+ 0, 171, 79, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h new file mode 100755 index 000000000..6e009f472 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h @@ -0,0 +1,195 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_TARGET 4 xyzw 4 TARGET int xyzw
+// SV_TARGET 5 xyzw 5 TARGET int xyzw
+// SV_TARGET 6 xyzw 6 TARGET int xyzw
+// SV_TARGET 7 xyzw 7 TARGET int xyzw
+//
+ps_4_0
+dcl_input_ps constant v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint[] =
+{
+ 68, 88, 66, 67, 206, 129,
+ 255, 236, 115, 217, 216, 20,
+ 88, 47, 155, 195, 145, 179,
+ 183, 28, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 0, 0, 0, 8, 0,
+ 0, 0, 8, 0, 0, 0,
+ 200, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 2, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 3, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 5, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 6, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 24, 1,
+ 0, 0, 64, 0, 0, 0,
+ 70, 0, 0, 0, 98, 8,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 3, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 5, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 6, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 7, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h new file mode 100755 index 000000000..f162b4449 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h @@ -0,0 +1,130 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearSint[] =
+{
+ 68, 88, 66, 67, 20, 240,
+ 85, 136, 255, 181, 253, 103,
+ 207, 181, 122, 106, 92, 25,
+ 228, 89, 1, 0, 0, 0,
+ 48, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 220, 0,
+ 0, 0, 48, 1, 0, 0,
+ 180, 1, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 72, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 7, 7, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 67, 79, 76,
+ 79, 82, 0, 171, 79, 83,
+ 71, 78, 76, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 67, 79, 76, 79,
+ 82, 0, 171, 171, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 16, 16, 0, 1, 0,
+ 0, 0, 103, 0, 0, 4,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h new file mode 100755 index 000000000..c53650bd8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h @@ -0,0 +1,195 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_TARGET 4 xyzw 4 TARGET uint xyzw
+// SV_TARGET 5 xyzw 5 TARGET uint xyzw
+// SV_TARGET 6 xyzw 6 TARGET uint xyzw
+// SV_TARGET 7 xyzw 7 TARGET uint xyzw
+//
+ps_4_0
+dcl_input_ps constant v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint[] =
+{
+ 68, 88, 66, 67, 117, 209,
+ 142, 159, 65, 29, 212, 206,
+ 242, 37, 169, 58, 35, 236,
+ 222, 73, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 0, 0, 0, 8, 0,
+ 0, 0, 8, 0, 0, 0,
+ 200, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 2, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 4, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 5, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 6, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 24, 1,
+ 0, 0, 64, 0, 0, 0,
+ 70, 0, 0, 0, 98, 8,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 3, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 5, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 6, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 7, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h new file mode 100755 index 000000000..cfad90f68 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h @@ -0,0 +1,130 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearUint[] =
+{
+ 68, 88, 66, 67, 62, 191,
+ 52, 95, 60, 98, 193, 75,
+ 194, 36, 187, 194, 54, 24,
+ 232, 224, 1, 0, 0, 0,
+ 48, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 220, 0,
+ 0, 0, 48, 1, 0, 0,
+ 180, 1, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 72, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 7, 7, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 67, 79, 76,
+ 79, 82, 0, 171, 79, 83,
+ 71, 78, 76, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 67, 79, 76, 79,
+ 82, 0, 171, 171, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 16, 16, 0, 1, 0,
+ 0, 0, 103, 0, 0, 4,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h new file mode 100755 index 000000000..050040e74 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h @@ -0,0 +1,177 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xy 0 NONE float xy
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg Constant Description
+// ---------- --------------------------------------------------
+// c0 Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+ vs_2_x
+ def c1, 0, 1, 0, 0
+ dcl_texcoord v0
+ dcl_texcoord1 v1
+ add oPos.xy, v0, c0
+ mov oPos.zw, c1.xyxy
+ mov oT0.xy, v1
+
+// approximately 3 instruction slots used
+vs_4_0
+dcl_input v0.xy
+dcl_input v1.xy
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xy
+mov o0.xy, v0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.xy, v1.xyxx
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_Passthrough2D[] =
+{
+ 68, 88, 66, 67, 230, 95,
+ 115, 230, 65, 211, 74, 82,
+ 143, 170, 109, 175, 63, 210,
+ 14, 229, 1, 0, 0, 0,
+ 216, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 200, 0, 0, 0, 88, 1,
+ 0, 0, 212, 1, 0, 0,
+ 44, 2, 0, 0, 128, 2,
+ 0, 0, 65, 111, 110, 57,
+ 136, 0, 0, 0, 136, 0,
+ 0, 0, 0, 2, 254, 255,
+ 96, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 0, 0,
+ 36, 0, 0, 0, 36, 0,
+ 1, 0, 36, 0, 0, 0,
+ 0, 0, 1, 2, 254, 255,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 0, 0,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 5, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 5, 0,
+ 1, 128, 1, 0, 15, 144,
+ 2, 0, 0, 3, 0, 0,
+ 3, 192, 0, 0, 228, 144,
+ 0, 0, 228, 160, 1, 0,
+ 0, 2, 0, 0, 12, 192,
+ 1, 0, 68, 160, 1, 0,
+ 0, 2, 0, 0, 3, 224,
+ 1, 0, 228, 144, 255, 255,
+ 0, 0, 83, 72, 68, 82,
+ 136, 0, 0, 0, 64, 0,
+ 1, 0, 34, 0, 0, 0,
+ 95, 0, 0, 3, 50, 16,
+ 16, 0, 0, 0, 0, 0,
+ 95, 0, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 103, 0, 0, 4, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 50, 32, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 54, 0, 0, 5,
+ 50, 32, 16, 0, 1, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 82, 68, 69, 70, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 28, 0, 0, 0,
+ 0, 4, 254, 255, 0, 1,
+ 0, 0, 28, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 76, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 3, 3,
+ 0, 0, 65, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 80, 79, 83, 73,
+ 84, 73, 79, 78, 0, 84,
+ 69, 88, 67, 79, 79, 82,
+ 68, 0, 171, 171, 79, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 12,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h new file mode 100755 index 000000000..ae2d9485e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h @@ -0,0 +1,191 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+gs_4_0
+dcl_input_siv v[3][0].xyzw, position
+dcl_input v[3][1].x
+dcl_input v[3][2].xyz
+dcl_temps 1
+dcl_inputprimitive triangle
+dcl_outputtopology trianglestrip
+dcl_output_siv o0.xyzw, position
+dcl_output_siv o1.x, rendertarget_array_index
+dcl_output o2.xyz
+dcl_maxout 3
+mov r0.x, l(0)
+loop
+ ige r0.y, r0.x, l(3)
+ breakc_nz r0.y
+ mov o0.xyzw, v[r0.x + 0][0].xyzw
+ mov o1.x, v[r0.x + 0][1].x
+ mov o2.xyz, v[r0.x + 0][2].xyzx
+ emit
+ iadd r0.x, r0.x, l(1)
+endloop
+ret
+// Approximately 11 instruction slots used
+#endif
+
+const BYTE g_GS_Passthrough3D[] =
+{
+ 68, 88, 66, 67, 92, 129,
+ 41, 170, 114, 75, 160, 250,
+ 95, 161, 230, 161, 11, 78,
+ 252, 65, 1, 0, 0, 0,
+ 72, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 0, 1,
+ 0, 0, 136, 1, 0, 0,
+ 204, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 83, 71, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 108, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 15, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 98, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 7, 7, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 76, 65, 89, 69, 82, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 14,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 8,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 83, 72, 68, 82,
+ 60, 1, 0, 0, 64, 0,
+ 2, 0, 79, 0, 0, 0,
+ 97, 0, 0, 5, 242, 16,
+ 32, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 95, 0, 0, 4,
+ 18, 16, 32, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 95, 0, 0, 4, 114, 16,
+ 32, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 93, 24, 0, 1, 92, 40,
+ 0, 1, 103, 0, 0, 4,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 103, 0, 0, 4, 18, 32,
+ 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 101, 0,
+ 0, 3, 114, 32, 16, 0,
+ 2, 0, 0, 0, 94, 0,
+ 0, 2, 3, 0, 0, 0,
+ 54, 0, 0, 5, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 48, 0, 0, 1,
+ 33, 0, 0, 7, 34, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 3, 0, 0, 0, 3, 0,
+ 4, 3, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 160, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 18, 32, 16, 0, 1, 0,
+ 0, 0, 10, 16, 160, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 7, 114, 32,
+ 16, 0, 2, 0, 0, 0,
+ 70, 18, 160, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 19, 0,
+ 0, 1, 30, 0, 0, 7,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0,
+ 22, 0, 0, 1, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 11, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 5, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h new file mode 100755 index 000000000..5701a4036 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h @@ -0,0 +1,155 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xy 0 NONE float xy
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+vs_4_0
+dcl_input v0.xy
+dcl_input v1.x
+dcl_input v2.xyz
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output o2.xyz
+mov o0.xy, v0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.x, v1.x
+mov o2.xyz, v2.xyzx
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_VS_Passthrough3D[] =
+{
+ 68, 88, 66, 67, 229, 65,
+ 217, 172, 143, 180, 152, 72,
+ 16, 12, 254, 66, 0, 215,
+ 50, 173, 1, 0, 0, 0,
+ 168, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 252, 0,
+ 0, 0, 112, 1, 0, 0,
+ 44, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 104, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 3, 3, 0, 0,
+ 89, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 7, 7, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 76, 65, 89,
+ 69, 82, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0,
+ 79, 83, 71, 78, 108, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 14, 0, 0, 98, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 8, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 76, 65,
+ 89, 69, 82, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 83, 72, 68, 82,
+ 180, 0, 0, 0, 64, 0,
+ 1, 0, 45, 0, 0, 0,
+ 95, 0, 0, 3, 50, 16,
+ 16, 0, 0, 0, 0, 0,
+ 95, 0, 0, 3, 18, 16,
+ 16, 0, 1, 0, 0, 0,
+ 95, 0, 0, 3, 114, 16,
+ 16, 0, 2, 0, 0, 0,
+ 103, 0, 0, 4, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 18, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 114, 32, 16, 0,
+ 2, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 54, 0, 0, 5,
+ 18, 32, 16, 0, 1, 0,
+ 0, 0, 10, 16, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0,
+ 2, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h new file mode 100755 index 000000000..38acea3aa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h @@ -0,0 +1,145 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output oDepth
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov oDepth, r0.x
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughDepth2D[] =
+{
+ 68, 88, 66, 67, 8, 33,
+ 154, 92, 164, 28, 139, 205,
+ 1, 168, 30, 229, 51, 127,
+ 173, 221, 1, 0, 0, 0,
+ 100, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 232, 1, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 255, 255,
+ 255, 255, 1, 14, 0, 0,
+ 83, 86, 95, 68, 69, 80,
+ 84, 72, 0, 171, 171, 171,
+ 83, 72, 68, 82, 120, 0,
+ 0, 0, 64, 0, 0, 0,
+ 30, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 2,
+ 1, 192, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 4, 1, 192,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h new file mode 100755 index 000000000..e0bcbc8fe --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h @@ -0,0 +1,196 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.x, c0.xxxy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum2D[] =
+{
+ 68, 88, 66, 67, 144, 18,
+ 242, 89, 150, 125, 18, 219,
+ 193, 196, 127, 207, 14, 165,
+ 198, 119, 1, 0, 0, 0,
+ 28, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 108, 1,
+ 0, 0, 232, 1, 0, 0,
+ 144, 2, 0, 0, 232, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 255, 255,
+ 104, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 0, 128, 0, 0,
+ 64, 160, 0, 0, 21, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 148, 0, 0, 0,
+ 64, 0, 0, 0, 37, 0,
+ 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 114, 32, 16, 0, 0, 0,
+ 0, 0, 6, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 160, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 109, 0,
+ 0, 0, 92, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h new file mode 100755 index 000000000..ac2bb4035 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h @@ -0,0 +1,160 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum3D[] =
+{
+ 68, 88, 66, 67, 173, 177,
+ 219, 35, 149, 130, 33, 215,
+ 183, 219, 250, 244, 100, 17,
+ 62, 106, 1, 0, 0, 0,
+ 176, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 52, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 148, 0,
+ 0, 0, 64, 0, 0, 0,
+ 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 6, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h new file mode 100755 index 000000000..88599fca9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h @@ -0,0 +1,185 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r0, r0.xxxw
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha2D[] =
+{
+ 68, 88, 66, 67, 246, 240,
+ 158, 208, 214, 197, 166, 221,
+ 45, 58, 235, 164, 12, 157,
+ 62, 31, 1, 0, 0, 0,
+ 232, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 176, 0, 0, 0, 56, 1,
+ 0, 0, 180, 1, 0, 0,
+ 92, 2, 0, 0, 180, 2,
+ 0, 0, 65, 111, 110, 57,
+ 112, 0, 0, 0, 112, 0,
+ 0, 0, 0, 2, 255, 255,
+ 72, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 1, 0,
+ 0, 2, 0, 0, 15, 128,
+ 0, 0, 192, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0, 83, 72, 68, 82,
+ 128, 0, 0, 0, 64, 0,
+ 0, 0, 32, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 6, 12, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h new file mode 100755 index 000000000..19091d035 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h @@ -0,0 +1,156 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha3D[] =
+{
+ 68, 88, 66, 67, 224, 152,
+ 208, 227, 44, 106, 62, 235,
+ 129, 97, 207, 213, 29, 232,
+ 163, 6, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 32, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 128, 0,
+ 0, 0, 64, 0, 0, 0,
+ 32, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 6, 12,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h new file mode 100755 index 000000000..d42101670 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h @@ -0,0 +1,198 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.x, c0.xyyy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2D[] =
+{
+ 68, 88, 66, 67, 212, 251,
+ 117, 250, 99, 185, 28, 44,
+ 178, 14, 83, 133, 173, 0,
+ 182, 196, 1, 0, 0, 0,
+ 40, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 120, 1,
+ 0, 0, 244, 1, 0, 0,
+ 156, 2, 0, 0, 244, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 255, 255,
+ 104, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 0, 128, 0, 0,
+ 84, 160, 0, 0, 21, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 160, 0, 0, 0,
+ 64, 0, 0, 0, 40, 0,
+ 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 18, 32, 16, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 8, 226, 32, 16, 0,
+ 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 160, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 109, 0,
+ 0, 0, 92, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h new file mode 100755 index 000000000..4d8d9933a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h @@ -0,0 +1,167 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DI[] =
+{
+ 68, 88, 66, 67, 123, 230,
+ 45, 18, 63, 217, 12, 210,
+ 151, 254, 16, 78, 107, 211,
+ 57, 255, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 12, 1, 0, 0, 64, 0,
+ 0, 0, 67, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 226, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h new file mode 100755 index 000000000..3f3885a1f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h @@ -0,0 +1,167 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DUI[] =
+{
+ 68, 88, 66, 67, 4, 26,
+ 62, 109, 94, 45, 124, 238,
+ 150, 245, 85, 155, 185, 37,
+ 234, 152, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 12, 1, 0, 0, 64, 0,
+ 0, 0, 67, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 226, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h new file mode 100755 index 000000000..506baef44 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h @@ -0,0 +1,162 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3D[] =
+{
+ 68, 88, 66, 67, 11, 235,
+ 208, 143, 219, 183, 141, 78,
+ 136, 182, 62, 182, 243, 12,
+ 239, 125, 1, 0, 0, 0,
+ 188, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 64, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 160, 0,
+ 0, 0, 64, 0, 0, 0,
+ 40, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 226, 32,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h new file mode 100755 index 000000000..89c35d600 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h @@ -0,0 +1,174 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3DI[] =
+{
+ 68, 88, 66, 67, 222, 251,
+ 30, 61, 15, 80, 81, 247,
+ 175, 137, 44, 19, 23, 84,
+ 149, 211, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 226, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h new file mode 100755 index 000000000..64386841c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h @@ -0,0 +1,174 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3DUI[] =
+{
+ 68, 88, 66, 67, 69, 5,
+ 86, 212, 201, 54, 97, 205,
+ 89, 161, 100, 72, 246, 114,
+ 40, 214, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 226, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h new file mode 100755 index 000000000..201cbff60 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h @@ -0,0 +1,198 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.xyxx, c0.xxyy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2D[] =
+{
+ 68, 88, 66, 67, 217, 171,
+ 153, 248, 26, 15, 102, 119,
+ 86, 174, 121, 245, 223, 83,
+ 2, 181, 1, 0, 0, 0,
+ 40, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 120, 1,
+ 0, 0, 244, 1, 0, 0,
+ 156, 2, 0, 0, 244, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 255, 255,
+ 104, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 4, 128, 0, 0,
+ 80, 160, 0, 0, 21, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 160, 0, 0, 0,
+ 64, 0, 0, 0, 40, 0,
+ 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 50, 32, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 8, 194, 32, 16, 0,
+ 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 160, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 109, 0,
+ 0, 0, 92, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h new file mode 100755 index 000000000..a66e53094 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h @@ -0,0 +1,167 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DI[] =
+{
+ 68, 88, 66, 67, 89, 123,
+ 129, 251, 206, 105, 221, 141,
+ 5, 160, 186, 187, 168, 157,
+ 145, 246, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 12, 1, 0, 0, 64, 0,
+ 0, 0, 67, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 194, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h new file mode 100755 index 000000000..5146cd936 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h @@ -0,0 +1,167 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DUI[] =
+{
+ 68, 88, 66, 67, 253, 188,
+ 138, 153, 226, 194, 182, 197,
+ 184, 36, 111, 24, 198, 171,
+ 241, 145, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 12, 1, 0, 0, 64, 0,
+ 0, 0, 67, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 194, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h new file mode 100755 index 000000000..a31301170 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h @@ -0,0 +1,162 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3D[] =
+{
+ 68, 88, 66, 67, 117, 159,
+ 238, 81, 51, 223, 126, 31,
+ 223, 171, 227, 2, 248, 7,
+ 72, 91, 1, 0, 0, 0,
+ 188, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 64, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 160, 0,
+ 0, 0, 64, 0, 0, 0,
+ 40, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h new file mode 100755 index 000000000..ef6ec1723 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h @@ -0,0 +1,174 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3DI[] =
+{
+ 68, 88, 66, 67, 62, 119,
+ 61, 21, 83, 42, 80, 125,
+ 121, 208, 247, 10, 223, 62,
+ 33, 18, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 194, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h new file mode 100755 index 000000000..d1540cee7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h @@ -0,0 +1,174 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3DUI[] =
+{
+ 68, 88, 66, 67, 37, 56,
+ 43, 206, 81, 137, 125, 191,
+ 216, 50, 86, 76, 61, 78,
+ 25, 246, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8,
+ 194, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h new file mode 100755 index 000000000..0047ef3ca --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h @@ -0,0 +1,196 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.xyzx, c0.xxxy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2D[] =
+{
+ 68, 88, 66, 67, 51, 90,
+ 49, 167, 211, 79, 20, 215,
+ 57, 227, 70, 56, 132, 117,
+ 66, 156, 1, 0, 0, 0,
+ 28, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 108, 1,
+ 0, 0, 232, 1, 0, 0,
+ 144, 2, 0, 0, 232, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 255, 255,
+ 104, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 36, 128, 0, 0,
+ 64, 160, 0, 0, 21, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 148, 0, 0, 0,
+ 64, 0, 0, 0, 37, 0,
+ 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 114, 32, 16, 0, 0, 0,
+ 0, 0, 70, 2, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70,
+ 160, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 109, 0,
+ 0, 0, 92, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h new file mode 100755 index 000000000..0f318fd8b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h @@ -0,0 +1,165 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DI[] =
+{
+ 68, 88, 66, 67, 16, 227,
+ 172, 190, 246, 118, 223, 239,
+ 176, 78, 90, 11, 135, 138,
+ 109, 174, 1, 0, 0, 0,
+ 196, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 72, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h new file mode 100755 index 000000000..943f7a2be --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h @@ -0,0 +1,165 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DUI[] =
+{
+ 68, 88, 66, 67, 245, 219,
+ 46, 32, 34, 74, 2, 47,
+ 124, 96, 216, 40, 253, 243,
+ 104, 178, 1, 0, 0, 0,
+ 196, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 72, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 0, 1, 0, 0, 64, 0,
+ 0, 0, 64, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h new file mode 100755 index 000000000..528f27361 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h @@ -0,0 +1,160 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3D[] =
+{
+ 68, 88, 66, 67, 3, 213,
+ 227, 200, 132, 255, 7, 95,
+ 0, 252, 77, 33, 254, 184,
+ 83, 110, 1, 0, 0, 0,
+ 176, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 52, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 148, 0,
+ 0, 0, 64, 0, 0, 0,
+ 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h new file mode 100755 index 000000000..fa2a63959 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h @@ -0,0 +1,172 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3DI[] =
+{
+ 68, 88, 66, 67, 194, 157,
+ 8, 194, 167, 235, 14, 127,
+ 69, 198, 32, 35, 167, 35,
+ 213, 248, 1, 0, 0, 0,
+ 232, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 108, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 244, 0, 0, 0, 64, 0,
+ 0, 0, 61, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h new file mode 100755 index 000000000..e90b40d00 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h @@ -0,0 +1,172 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3DUI[] =
+{
+ 68, 88, 66, 67, 253, 147,
+ 1, 158, 41, 31, 253, 138,
+ 52, 213, 103, 41, 188, 192,
+ 79, 199, 1, 0, 0, 0,
+ 232, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 108, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 244, 0, 0, 0, 64, 0,
+ 0, 0, 61, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h new file mode 100755 index 000000000..a4ee9d5ab --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h @@ -0,0 +1,176 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+sample o0.xyzw, v1.xyxx, t0.xyzw, s0
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2D[] =
+{
+ 68, 88, 66, 67, 240, 186,
+ 163, 221, 151, 45, 139, 68,
+ 172, 121, 30, 230, 203, 102,
+ 92, 33, 1, 0, 0, 0,
+ 192, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 164, 0, 0, 0, 16, 1,
+ 0, 0, 140, 1, 0, 0,
+ 52, 2, 0, 0, 140, 2,
+ 0, 0, 65, 111, 110, 57,
+ 100, 0, 0, 0, 100, 0,
+ 0, 0, 0, 2, 255, 255,
+ 60, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 40, 0,
+ 0, 0, 40, 0, 0, 0,
+ 40, 0, 1, 0, 36, 0,
+ 0, 0, 40, 0, 0, 0,
+ 0, 0, 1, 2, 255, 255,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0, 83, 72, 68, 82,
+ 100, 0, 0, 0, 64, 0,
+ 0, 0, 25, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 69, 0,
+ 0, 9, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 82, 68, 69, 70, 160, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1,
+ 0, 0, 109, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 100, 0, 0, 0,
+ 2, 0, 0, 0, 5, 0,
+ 0, 0, 4, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 13, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 70, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h new file mode 100755 index 000000000..d87d043d8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h @@ -0,0 +1,157 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DI[] =
+{
+ 68, 88, 66, 67, 81, 147,
+ 194, 141, 92, 236, 184, 192,
+ 11, 249, 14, 215, 122, 110,
+ 35, 111, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 32, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 216, 0, 0, 0, 64, 0,
+ 0, 0, 54, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 7, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h new file mode 100755 index 000000000..35cff53a4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h @@ -0,0 +1,157 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DUI[] =
+{
+ 68, 88, 66, 67, 128, 252,
+ 255, 238, 68, 109, 10, 133,
+ 175, 163, 216, 152, 219, 103,
+ 163, 223, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 32, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 80, 0,
+ 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 216, 0, 0, 0, 64, 0,
+ 0, 0, 54, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 7, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h new file mode 100755 index 000000000..ac4cbeae9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h @@ -0,0 +1,149 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+sample o0.xyzw, v2.xyzx, t0.xyzw, s0
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3D[] =
+{
+ 68, 88, 66, 67, 246, 41,
+ 15, 240, 168, 172, 91, 145,
+ 236, 221, 187, 89, 12, 0,
+ 93, 149, 1, 0, 0, 0,
+ 128, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 4, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 70,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 100, 0,
+ 0, 0, 64, 0, 0, 0,
+ 25, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 40,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 114, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h new file mode 100755 index 000000000..1921c9f20 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h @@ -0,0 +1,164 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3DI[] =
+{
+ 68, 88, 66, 67, 139, 158,
+ 6, 251, 163, 134, 3, 183,
+ 5, 227, 185, 108, 35, 91,
+ 67, 191, 1, 0, 0, 0,
+ 192, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 68, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 69, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 204, 0, 0, 0, 64, 0,
+ 0, 0, 51, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 7, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h new file mode 100755 index 000000000..cba1502da --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h @@ -0,0 +1,164 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3DUI[] =
+{
+ 68, 88, 66, 67, 16, 111,
+ 56, 218, 148, 233, 100, 164,
+ 0, 199, 73, 155, 213, 171,
+ 78, 18, 1, 0, 0, 0,
+ 192, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 68, 2, 0, 0, 82, 68,
+ 69, 70, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 70, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 85, 73, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 7, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 204, 0, 0, 0, 64, 0,
+ 0, 0, 51, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 7, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h new file mode 100755 index 000000000..3ce18ee6b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h @@ -0,0 +1,101 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0.xyz, r0.w, r0
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBAPremultiply2D[] = {
+ 68, 88, 66, 67, 139, 254, 84, 241, 202, 33, 132, 221, 123, 19, 241, 182, 75, 155, 177,
+ 115, 1, 0, 0, 0, 8, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 180, 0,
+ 0, 0, 88, 1, 0, 0, 212, 1, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 65,
+ 111, 110, 57, 116, 0, 0, 0, 116, 0, 0, 0, 0, 2, 255, 255, 76, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15,
+ 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0,
+ 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0,
+ 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0,
+ 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0,
+ 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0,
+ 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56, 52, 0, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95,
+ 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h new file mode 100755 index 000000000..c1354f740 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h @@ -0,0 +1,110 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ rcp r1.w, r0.w
+ mul r1.xyz, r0, r1.w
+ cmp r0.xyz, -r0.w, r0, r1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBAUnmultiply2D[] = {
+ 68, 88, 66, 67, 180, 87, 43, 111, 255, 135, 28, 224, 42, 85, 197, 16, 17, 172, 176,
+ 70, 1, 0, 0, 0, 104, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 212, 0,
+ 0, 0, 184, 1, 0, 0, 52, 2, 0, 0, 220, 2, 0, 0, 52, 3, 0, 0, 65,
+ 111, 110, 57, 148, 0, 0, 0, 148, 0, 0, 0, 0, 2, 255, 255, 108, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 6, 0, 0, 2,
+ 1, 0, 8, 128, 0, 0, 255, 128, 5, 0, 0, 3, 1, 0, 7, 128, 0, 0, 228,
+ 128, 1, 0, 255, 128, 88, 0, 0, 4, 0, 0, 7, 128, 0, 0, 255, 129, 0, 0,
+ 228, 128, 1, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255,
+ 255, 0, 0, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16,
+ 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2,
+ 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0,
+ 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1,
+ 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0,
+ 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 160, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0,
+ 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83,
+ 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2,
+ 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0,
+ 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h new file mode 100755 index 000000000..c88a1414b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h @@ -0,0 +1,101 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0.xyz, r0.w, r0
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBPremultiply2D[] = {
+ 68, 88, 66, 67, 139, 254, 84, 241, 202, 33, 132, 221, 123, 19, 241, 182, 75, 155, 177,
+ 115, 1, 0, 0, 0, 8, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 180, 0,
+ 0, 0, 88, 1, 0, 0, 212, 1, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 65,
+ 111, 110, 57, 116, 0, 0, 0, 116, 0, 0, 0, 0, 2, 255, 255, 76, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15,
+ 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0,
+ 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0,
+ 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0,
+ 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0,
+ 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0,
+ 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56, 52, 0, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95,
+ 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h new file mode 100755 index 000000000..9dd3c02f3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h @@ -0,0 +1,110 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ rcp r1.w, r0.w
+ mul r1.xyz, r0, r1.w
+ cmp r0.xyz, -r0.w, r0, r1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBUnmultiply2D[] = {
+ 68, 88, 66, 67, 180, 87, 43, 111, 255, 135, 28, 224, 42, 85, 197, 16, 17, 172, 176,
+ 70, 1, 0, 0, 0, 104, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 212, 0,
+ 0, 0, 184, 1, 0, 0, 52, 2, 0, 0, 220, 2, 0, 0, 52, 3, 0, 0, 65,
+ 111, 110, 57, 148, 0, 0, 0, 148, 0, 0, 0, 0, 2, 255, 255, 108, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 6, 0, 0, 2,
+ 1, 0, 8, 128, 0, 0, 255, 128, 5, 0, 0, 3, 1, 0, 7, 128, 0, 0, 228,
+ 128, 1, 0, 255, 128, 88, 0, 0, 4, 0, 0, 7, 128, 0, 0, 255, 129, 0, 0,
+ 228, 128, 1, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255,
+ 255, 0, 0, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16,
+ 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2,
+ 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0,
+ 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1,
+ 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0,
+ 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 160, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0,
+ 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83,
+ 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2,
+ 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0,
+ 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h new file mode 100755 index 000000000..b44a27c58 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h @@ -0,0 +1,82 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Depth texture float 2dMS 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 x 0 TARGET float x
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.x
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.x, r0.xyzw, t0.xyzw, l(0)
+mov o0.x, r0.x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveDepth[] = {
+ 68, 88, 66, 67, 205, 219, 191, 201, 103, 134, 243, 76, 11, 91, 23, 182, 42, 8, 17,
+ 173, 1, 0, 0, 0, 184, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 176, 0,
+ 0, 0, 8, 1, 0, 0, 60, 1, 0, 0, 60, 2, 0, 0, 82, 68, 69, 70, 116,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 66, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 68, 101, 112, 116, 104, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 111, 115, 105,
+ 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 14, 0, 0,
+ 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 248, 0, 0,
+ 0, 65, 0, 0, 0, 62, 0, 0, 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1,
+ 0, 0, 0, 101, 0, 0, 3, 18, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 61, 16, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0,
+ 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50,
+ 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 28, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46,
+ 0, 0, 9, 18, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h new file mode 100755 index 000000000..58834eb65 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h @@ -0,0 +1,92 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Depth texture float 2dMS 0 1
+// Stencil texture uint2 2dMS 1 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xy 0 TARGET float xy
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1
+dcl_input_ps linear v1.xy
+dcl_output o0.xy
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.z, r0.xyzw, t1.xzyw, l(0)
+ldms r0.x, r0.xyww, t0.xyzw, l(0)
+mov o0.x, r0.x
+utof o0.y, r0.z
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveDepthStencil[] = {
+ 68, 88, 66, 67, 229, 191, 254, 12, 10, 19, 181, 162, 222, 203, 244, 146, 104, 226, 195,
+ 177, 1, 0, 0, 0, 40, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 216, 0,
+ 0, 0, 48, 1, 0, 0, 100, 1, 0, 0, 172, 2, 0, 0, 82, 68, 69, 70, 156,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 106, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 98, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0,
+ 68, 101, 112, 116, 104, 0, 83, 116, 101, 110, 99, 105, 108, 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 111,
+ 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 12,
+ 0, 0, 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 64,
+ 1, 0, 0, 65, 0, 0, 0, 80, 0, 0, 0, 106, 8, 0, 1, 88, 32, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 88, 32, 0, 4, 0, 112, 16,
+ 0, 1, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3, 50, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1,
+ 0, 0, 0, 28, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0,
+ 0, 9, 66, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 134,
+ 125, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 46, 0, 0, 9,
+ 18, 0, 16, 0, 0, 0, 0, 0, 70, 15, 16, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 18, 32,
+ 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 34,
+ 32, 16, 0, 0, 0, 0, 0, 42, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h new file mode 100755 index 000000000..989a316f6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h @@ -0,0 +1,84 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xy 1 NONE float xy
+//
+vs_4_1
+dcl_globalFlags refactoringAllowed
+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0},
+ { -1.000000, -1.000000, 0, 0},
+ { -1.000000, 1.000000, 0, 0},
+ { 1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0} }
+dcl_input_sgv v0.x, vertex_id
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xy
+dcl_temps 1
+mov o0.zw, l(0,0,0,1.000000)
+mov r0.x, v0.x
+mov o0.xy, icb[r0.x + 0].xyxx
+add r0.y, l(1.000000), icb[r0.x + 0].x
+add r0.x, l(1.000000), -icb[r0.x + 0].y
+mul o1.xy, r0.yxyy, l(0.500000, 0.500000, 0.000000, 0.000000)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_VS_ResolveDepthStencil[] = {
+ 68, 88, 66, 67, 205, 15, 103, 70, 202, 235, 195, 98, 255, 82, 84, 239, 130, 6, 12,
+ 104, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 140, 0,
+ 0, 0, 192, 0, 0, 0, 24, 1, 0, 0, 132, 2, 0, 0, 82, 68, 69, 70, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171, 171, 73, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 86, 101, 114, 116, 101, 120, 73,
+ 68, 0, 79, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 1, 0, 0, 0, 3, 12, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111,
+ 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 83, 72, 68, 82, 100,
+ 1, 0, 0, 65, 0, 1, 0, 89, 0, 0, 0, 106, 8, 0, 1, 53, 24, 0, 0,
+ 26, 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 128, 63, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 191, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 191, 0,
+ 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 191, 0, 0, 0,
+ 0, 0, 0, 0, 0, 96, 0, 0, 4, 18, 16, 16, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 101,
+ 0, 0, 3, 50, 32, 16, 0, 1, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 54, 0, 0, 5, 18, 0,
+ 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 50,
+ 32, 16, 0, 0, 0, 0, 0, 70, 144, 144, 0, 10, 0, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 34, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128,
+ 63, 10, 144, 144, 0, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 9, 18, 0,
+ 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 26, 144, 144, 128, 65,
+ 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 50, 32, 16, 0,
+ 1, 0, 0, 0, 22, 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 3,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h new file mode 100755 index 000000000..1730df345 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h @@ -0,0 +1,84 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Stencil texture uint2 2dMS 1 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xy 0 TARGET float xy
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1
+dcl_input_ps linear v1.xy
+dcl_output o0.xy
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t1.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.x, r0.xyzw, t1.yxzw, l(0)
+utof o0.y, r0.x
+mov o0.x, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveStencil[] = {
+ 68, 88, 66, 67, 122, 29, 34, 146, 254, 203, 175, 97, 151, 254, 255, 190, 91, 40, 55,
+ 118, 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 180, 0,
+ 0, 0, 12, 1, 0, 0, 64, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 120,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 68, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 5, 0, 0, 0, 83, 116, 101, 110, 99, 105, 108, 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52, 0, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95,
+ 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 3, 12, 0, 0, 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68,
+ 82, 12, 1, 0, 0, 65, 0, 0, 0, 67, 0, 0, 0, 106, 8, 0, 1, 88, 32,
+ 0, 4, 0, 112, 16, 0, 1, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 50,
+ 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 50, 32, 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 50, 0, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 1, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0, 0, 0, 28, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0,
+ 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 46, 0, 0, 9, 18, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 22, 126, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 86, 0, 0, 5, 34, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h new file mode 100755 index 000000000..b34914b39 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h @@ -0,0 +1,278 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF2DArray texture float4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 18 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF2DArray[] =
+{
+ 68, 88, 66, 67, 39, 232,
+ 91, 166, 165, 217, 22, 39,
+ 183, 202, 191, 64, 238, 104,
+ 217, 199, 1, 0, 0, 0,
+ 204, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 104, 1, 0, 0, 240, 1,
+ 0, 0, 36, 2, 0, 0,
+ 80, 4, 0, 0, 82, 68,
+ 69, 70, 44, 1, 0, 0,
+ 1, 0, 0, 0, 168, 0,
+ 0, 0, 3, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 248, 0, 0, 0, 124, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 132, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 5, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 148, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 70, 50, 68, 65, 114,
+ 114, 97, 121, 0, 83, 119,
+ 105, 122, 122, 108, 101, 80,
+ 114, 111, 112, 101, 114, 116,
+ 105, 101, 115, 0, 171, 171,
+ 148, 0, 0, 0, 1, 0,
+ 0, 0, 192, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 216, 0, 0, 0, 0, 0,
+ 0, 0, 16, 0, 0, 0,
+ 2, 0, 0, 0, 232, 0,
+ 0, 0, 0, 0, 0, 0,
+ 83, 119, 105, 122, 122, 108,
+ 101, 73, 110, 100, 105, 99,
+ 101, 115, 0, 171, 1, 0,
+ 19, 0, 1, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 128, 0,
+ 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 118, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 86,
+ 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89,
+ 73, 78, 68, 69, 88, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82,
+ 36, 2, 0, 0, 64, 0,
+ 0, 0, 137, 0, 0, 0,
+ 89, 0, 0, 4, 70, 142,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 64,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 4, 0, 0, 0,
+ 86, 0, 0, 5, 66, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 16, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 2, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 34, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 66, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 18, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h new file mode 100755 index 000000000..ea57e8737 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h @@ -0,0 +1,256 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF2D texture float4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 16 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF2D[] =
+{
+ 68, 88, 66, 67, 187, 204,
+ 160, 39, 195, 158, 245, 72,
+ 125, 249, 70, 140, 158, 199,
+ 246, 220, 1, 0, 0, 0,
+ 96, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 1, 0, 0, 188, 1,
+ 0, 0, 240, 1, 0, 0,
+ 228, 3, 0, 0, 82, 68,
+ 69, 70, 40, 1, 0, 0,
+ 1, 0, 0, 0, 164, 0,
+ 0, 0, 3, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 244, 0, 0, 0, 124, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 132, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 143, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 70, 50, 68, 0, 83,
+ 119, 105, 122, 122, 108, 101,
+ 80, 114, 111, 112, 101, 114,
+ 116, 105, 101, 115, 0, 171,
+ 171, 171, 143, 0, 0, 0,
+ 1, 0, 0, 0, 188, 0,
+ 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0,
+ 0, 0, 0, 0, 16, 0,
+ 0, 0, 2, 0, 0, 0,
+ 228, 0, 0, 0, 0, 0,
+ 0, 0, 83, 119, 105, 122,
+ 122, 108, 101, 73, 110, 100,
+ 105, 99, 101, 115, 0, 171,
+ 1, 0, 19, 0, 1, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171, 83, 72,
+ 68, 82, 236, 1, 0, 0,
+ 64, 0, 0, 0, 123, 0,
+ 0, 0, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 105, 0, 0, 4, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 4, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 34, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 66, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 16, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h new file mode 100755 index 000000000..7938639e6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h @@ -0,0 +1,265 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF3D texture float4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 16 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF3D[] =
+{
+ 68, 88, 66, 67, 238, 60,
+ 80, 74, 42, 65, 120, 165,
+ 177, 91, 253, 216, 89, 102,
+ 2, 228, 1, 0, 0, 0,
+ 144, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 1, 0, 0, 236, 1,
+ 0, 0, 32, 2, 0, 0,
+ 20, 4, 0, 0, 82, 68,
+ 69, 70, 40, 1, 0, 0,
+ 1, 0, 0, 0, 164, 0,
+ 0, 0, 3, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 244, 0, 0, 0, 124, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 132, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 143, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 83, 97,
+ 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 70, 51, 68, 0, 83,
+ 119, 105, 122, 122, 108, 101,
+ 80, 114, 111, 112, 101, 114,
+ 116, 105, 101, 115, 0, 171,
+ 171, 171, 143, 0, 0, 0,
+ 1, 0, 0, 0, 188, 0,
+ 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0,
+ 0, 0, 0, 0, 16, 0,
+ 0, 0, 2, 0, 0, 0,
+ 228, 0, 0, 0, 0, 0,
+ 0, 0, 83, 119, 105, 122,
+ 122, 108, 101, 73, 110, 100,
+ 105, 99, 101, 115, 0, 171,
+ 1, 0, 19, 0, 1, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 128, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 118, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 7, 7, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 83, 86, 95, 82, 69, 78,
+ 68, 69, 82, 84, 65, 82,
+ 71, 69, 84, 65, 82, 82,
+ 65, 89, 73, 78, 68, 69,
+ 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171, 83, 72,
+ 68, 82, 236, 1, 0, 0,
+ 64, 0, 0, 0, 123, 0,
+ 0, 0, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 88, 40, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16,
+ 0, 3, 114, 16, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 105, 0, 0, 4, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 4, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 34, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 66, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 16, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h new file mode 100755 index 000000000..76176fcbe --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h @@ -0,0 +1,286 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI2DArray texture sint4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 22 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI2DArray[] =
+{
+ 68, 88, 66, 67, 85, 61,
+ 60, 36, 33, 245, 58, 113,
+ 238, 227, 230, 200, 136, 227,
+ 36, 193, 1, 0, 0, 0,
+ 240, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 64, 1, 0, 0, 200, 1,
+ 0, 0, 252, 1, 0, 0,
+ 116, 4, 0, 0, 82, 68,
+ 69, 70, 4, 1, 0, 0,
+ 1, 0, 0, 0, 128, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 208, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 5, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 108, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 73, 50, 68,
+ 65, 114, 114, 97, 121, 0,
+ 83, 119, 105, 122, 122, 108,
+ 101, 80, 114, 111, 112, 101,
+ 114, 116, 105, 101, 115, 0,
+ 171, 171, 108, 0, 0, 0,
+ 1, 0, 0, 0, 152, 0,
+ 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 176, 0, 0, 0,
+ 0, 0, 0, 0, 16, 0,
+ 0, 0, 2, 0, 0, 0,
+ 192, 0, 0, 0, 0, 0,
+ 0, 0, 83, 119, 105, 122,
+ 122, 108, 101, 73, 110, 100,
+ 105, 99, 101, 115, 0, 171,
+ 1, 0, 19, 0, 1, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 128, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 118, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 7, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 83, 86, 95, 82, 69, 78,
+ 68, 69, 82, 84, 65, 82,
+ 71, 69, 84, 65, 82, 82,
+ 65, 89, 73, 78, 68, 69,
+ 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171, 83, 72,
+ 68, 82, 112, 2, 0, 0,
+ 64, 0, 0, 0, 156, 0,
+ 0, 0, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 88, 64, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 51, 51, 0, 0, 100, 8,
+ 0, 4, 18, 16, 16, 0,
+ 1, 0, 0, 0, 4, 0,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 105, 0,
+ 0, 4, 0, 0, 0, 0,
+ 6, 0, 0, 0, 4, 0,
+ 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 86, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 7,
+ 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 2, 0, 0, 0,
+ 27, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 66, 0, 16, 0, 0, 0,
+ 0, 0, 10, 16, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 130, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 45, 0, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 34, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 66, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 22, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h new file mode 100755 index 000000000..1df27a0bf --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h @@ -0,0 +1,270 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI2D texture sint4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI2D[] =
+{
+ 68, 88, 66, 67, 180, 37,
+ 54, 19, 39, 134, 185, 230,
+ 234, 82, 113, 129, 69, 135,
+ 140, 27, 1, 0, 0, 0,
+ 164, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 148, 1,
+ 0, 0, 200, 1, 0, 0,
+ 40, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 204, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 73, 50, 68,
+ 0, 83, 119, 105, 122, 122,
+ 108, 101, 80, 114, 111, 112,
+ 101, 114, 116, 105, 101, 115,
+ 0, 171, 171, 171, 103, 0,
+ 0, 0, 1, 0, 0, 0,
+ 148, 0, 0, 0, 16, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 172, 0,
+ 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 2, 0,
+ 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119,
+ 105, 122, 122, 108, 101, 73,
+ 110, 100, 105, 99, 101, 115,
+ 0, 171, 1, 0, 19, 0,
+ 1, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 88, 2,
+ 0, 0, 64, 0, 0, 0,
+ 150, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 51, 51, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 26, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 34, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 42, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 66, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 58, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 21, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h new file mode 100755 index 000000000..96f042b5b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h @@ -0,0 +1,277 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI3D texture sint4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI3D[] =
+{
+ 68, 88, 66, 67, 48, 84,
+ 97, 193, 216, 245, 101, 196,
+ 167, 81, 215, 168, 25, 164,
+ 144, 38, 1, 0, 0, 0,
+ 200, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 196, 1,
+ 0, 0, 248, 1, 0, 0,
+ 76, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 204, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 73, 51, 68,
+ 0, 83, 119, 105, 122, 122,
+ 108, 101, 80, 114, 111, 112,
+ 101, 114, 116, 105, 101, 115,
+ 0, 171, 171, 171, 103, 0,
+ 0, 0, 1, 0, 0, 0,
+ 148, 0, 0, 0, 16, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 172, 0,
+ 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 2, 0,
+ 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119,
+ 105, 122, 122, 108, 101, 73,
+ 110, 100, 105, 99, 101, 115,
+ 0, 171, 1, 0, 19, 0,
+ 1, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 76, 2,
+ 0, 0, 64, 0, 0, 0,
+ 147, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 51, 51, 0, 0,
+ 98, 16, 0, 3, 114, 16,
+ 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 26, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 34, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 42, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 66, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 58, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 21, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h new file mode 100755 index 000000000..cca965c6f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h @@ -0,0 +1,286 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI2DArray texture uint4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 22 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI2DArray[] =
+{
+ 68, 88, 66, 67, 15, 124,
+ 179, 49, 45, 69, 64, 249,
+ 216, 189, 135, 190, 71, 234,
+ 72, 20, 1, 0, 0, 0,
+ 240, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 64, 1, 0, 0, 200, 1,
+ 0, 0, 252, 1, 0, 0,
+ 116, 4, 0, 0, 82, 68,
+ 69, 70, 4, 1, 0, 0,
+ 1, 0, 0, 0, 128, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 208, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 5, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 85, 73, 50,
+ 68, 65, 114, 114, 97, 121,
+ 0, 83, 119, 105, 122, 122,
+ 108, 101, 80, 114, 111, 112,
+ 101, 114, 116, 105, 101, 115,
+ 0, 171, 109, 0, 0, 0,
+ 1, 0, 0, 0, 152, 0,
+ 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 176, 0, 0, 0,
+ 0, 0, 0, 0, 16, 0,
+ 0, 0, 2, 0, 0, 0,
+ 192, 0, 0, 0, 0, 0,
+ 0, 0, 83, 119, 105, 122,
+ 122, 108, 101, 73, 110, 100,
+ 105, 99, 101, 115, 0, 171,
+ 1, 0, 19, 0, 1, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 128, 0, 0, 0, 3, 0,
+ 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 118, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 7, 3, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 83, 86, 95, 82, 69, 78,
+ 68, 69, 82, 84, 65, 82,
+ 71, 69, 84, 65, 82, 82,
+ 65, 89, 73, 78, 68, 69,
+ 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171, 83, 72,
+ 68, 82, 112, 2, 0, 0,
+ 64, 0, 0, 0, 156, 0,
+ 0, 0, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 88, 64, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 68, 68, 0, 0, 100, 8,
+ 0, 4, 18, 16, 16, 0,
+ 1, 0, 0, 0, 4, 0,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 105, 0,
+ 0, 4, 0, 0, 0, 0,
+ 6, 0, 0, 0, 4, 0,
+ 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 86, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 7,
+ 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 2, 0, 0, 0,
+ 27, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 66, 0, 16, 0, 0, 0,
+ 0, 0, 10, 16, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 130, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 45, 0, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 34, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 42, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 66, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 22, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h new file mode 100755 index 000000000..9de8b28a8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h @@ -0,0 +1,270 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI2D texture uint4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI2D[] =
+{
+ 68, 88, 66, 67, 165, 190,
+ 35, 188, 235, 202, 154, 237,
+ 226, 86, 223, 212, 34, 38,
+ 81, 252, 1, 0, 0, 0,
+ 164, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 148, 1,
+ 0, 0, 200, 1, 0, 0,
+ 40, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 204, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 85, 73, 50,
+ 68, 0, 83, 119, 105, 122,
+ 122, 108, 101, 80, 114, 111,
+ 112, 101, 114, 116, 105, 101,
+ 115, 0, 171, 171, 104, 0,
+ 0, 0, 1, 0, 0, 0,
+ 148, 0, 0, 0, 16, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 172, 0,
+ 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 2, 0,
+ 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119,
+ 105, 122, 122, 108, 101, 73,
+ 110, 100, 105, 99, 101, 115,
+ 0, 171, 1, 0, 19, 0,
+ 1, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 88, 2,
+ 0, 0, 64, 0, 0, 0,
+ 150, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 68, 68, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 27, 0,
+ 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 0,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 26, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 34, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 42, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 66, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 58, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 21, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h new file mode 100755 index 000000000..c66821602 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h @@ -0,0 +1,277 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI3D texture uint4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer cb0[1], immediateIndexed
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI3D[] =
+{
+ 68, 88, 66, 67, 186, 124,
+ 222, 110, 186, 145, 165, 56,
+ 152, 97, 247, 114, 115, 197,
+ 159, 190, 1, 0, 0, 0,
+ 200, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 196, 1,
+ 0, 0, 248, 1, 0, 0,
+ 76, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 204, 0, 0, 0, 92, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 84, 101, 120, 116,
+ 117, 114, 101, 85, 73, 51,
+ 68, 0, 83, 119, 105, 122,
+ 122, 108, 101, 80, 114, 111,
+ 112, 101, 114, 116, 105, 101,
+ 115, 0, 171, 171, 104, 0,
+ 0, 0, 1, 0, 0, 0,
+ 148, 0, 0, 0, 16, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 172, 0,
+ 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 2, 0,
+ 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119,
+ 105, 122, 122, 108, 101, 73,
+ 110, 100, 105, 99, 101, 115,
+ 0, 171, 1, 0, 19, 0,
+ 1, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 73, 83,
+ 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 2, 0, 0, 0, 7, 7,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82,
+ 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65,
+ 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 76, 2,
+ 0, 0, 64, 0, 0, 0,
+ 147, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 68, 68, 0, 0,
+ 98, 16, 0, 3, 114, 16,
+ 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4,
+ 0, 0, 0, 0, 6, 0,
+ 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 7, 114, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0,
+ 0, 0, 70, 18, 16, 0,
+ 2, 0, 0, 0, 27, 0,
+ 0, 5, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 45, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 18, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 26, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 7, 34, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48,
+ 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 42, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7,
+ 66, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 58, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 21, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat new file mode 100755 index 000000000..4c64b09a8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat @@ -0,0 +1,134 @@ +@ECHO OFF
+REM
+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+setlocal
+set errorCount=0
+set successCount=0
+set debug=0
+
+if "%1" == "debug" (
+ set debug=1
+)
+if "%1" == "release" (
+ set debug=0
+)
+
+:: Shaders for OpenGL ES 2.0 and OpenGL ES 3.0+
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Passthrough2D11.hlsl VS_Passthrough2D vs_4_0_level_9_3 compiled\passthrough2d11vs.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2D ps_4_0_level_9_3 compiled\passthroughrgba2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2D ps_4_0_level_9_3 compiled\passthroughrgb2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2D ps_4_0_level_9_3 compiled\passthroughrg2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2D ps_4_0_level_9_3 compiled\passthroughr2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLum2D ps_4_0_level_9_3 compiled\passthroughlum2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLumAlpha2D ps_4_0_level_9_3 compiled\passthroughlumalpha2d11ps.h %debug%
+
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAPremultiply2D ps_4_0_level_9_3 compiled\passthroughrgbapremultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAUnmultiply2D ps_4_0_level_9_3 compiled\passthroughrgbaunmultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBPremultiply2D ps_4_0_level_9_3 compiled\passthroughrgbpremultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBUnmultiply2D ps_4_0_level_9_3 compiled\passthroughrgbunmultiply2d11ps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearFloat vs_4_0_level_9_3 compiled\clearfloat11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearFloat_FL9 ps_4_0_level_9_3 compiled\clearfloat11_fl9ps.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearFloat ps_4_0 compiled\clearfloat11ps.h %debug%
+
+
+:: Shaders for OpenGL ES 3.0+ only
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughDepth2D ps_4_0 compiled\passthroughdepth2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2DUI ps_4_0 compiled\passthroughrgba2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2DI ps_4_0 compiled\passthroughrgba2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2DUI ps_4_0 compiled\passthroughrgb2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2DI ps_4_0 compiled\passthroughrgb2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2DUI ps_4_0 compiled\passthroughrg2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2DI ps_4_0 compiled\passthroughrg2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2DUI ps_4_0 compiled\passthroughr2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2DI ps_4_0 compiled\passthroughr2di11ps.h %debug%
+
+call:BuildShader Passthrough3D11.hlsl VS_Passthrough3D vs_4_0 compiled\passthrough3d11vs.h %debug%
+call:BuildShader Passthrough3D11.hlsl GS_Passthrough3D gs_4_0 compiled\passthrough3d11gs.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3D ps_4_0 compiled\passthroughrgba3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3DUI ps_4_0 compiled\passthroughrgba3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3DI ps_4_0 compiled\passthroughrgba3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3D ps_4_0 compiled\passthroughrgb3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3DUI ps_4_0 compiled\passthroughrgb3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3DI ps_4_0 compiled\passthroughrgb3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3D ps_4_0 compiled\passthroughrg3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3DUI ps_4_0 compiled\passthroughrg3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3DI ps_4_0 compiled\passthroughrg3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3D ps_4_0 compiled\passthroughr3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3DUI ps_4_0 compiled\passthroughr3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3DI ps_4_0 compiled\passthroughr3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughLum3D ps_4_0 compiled\passthroughlum3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughLumAlpha3D ps_4_0 compiled\passthroughlumalpha3d11ps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF2D ps_4_0 compiled\swizzlef2dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI2D ps_4_0 compiled\swizzlei2dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI2D ps_4_0 compiled\swizzleui2dps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF3D ps_4_0 compiled\swizzlef3dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI3D ps_4_0 compiled\swizzlei3dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI3D ps_4_0 compiled\swizzleui3dps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF2DArray ps_4_0 compiled\swizzlef2darrayps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI2DArray ps_4_0 compiled\swizzlei2darrayps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI2DArray ps_4_0 compiled\swizzleui2darrayps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearUint vs_4_0 compiled\clearuint11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearUint ps_4_0 compiled\clearuint11ps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearSint vs_4_0 compiled\clearsint11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearSint ps_4_0 compiled\clearsint11ps.h %debug%
+
+call:BuildShader BufferToTexture11.hlsl VS_BufferToTexture vs_4_0 compiled/buffertotexture11_vs.h %debug%
+call:BuildShader BufferToTexture11.hlsl GS_BufferToTexture gs_4_0 compiled/buffertotexture11_gs.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4F ps_4_0 compiled/buffertotexture11_ps_4f.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4I ps_4_0 compiled/buffertotexture11_ps_4i.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4UI ps_4_0 compiled/buffertotexture11_ps_4ui.h %debug%
+
+call:BuildShader ResolveDepthStencil.hlsl VS_ResolveDepthStencil vs_4_1 compiled/resolvedepthstencil11_vs.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveDepth ps_4_1 compiled/resolvedepth11_ps.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveDepthStencil ps_4_1 compiled/resolvedepthstencil11_ps.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveStencil ps_4_1 compiled/resolvestencil11_ps.h %debug%
+
+echo.
+
+if %successCount% GTR 0 (
+ echo %successCount% shaders compiled successfully.
+)
+if %errorCount% GTR 0 (
+ echo There were %errorCount% shader compilation errors.
+)
+
+endlocal
+exit /b
+
+:BuildShader
+set input=%~1
+set entry=%~2
+set type=%~3
+set output=%~4
+set debug=%~5
+
+if %debug% == 0 (
+ set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"
+) else (
+ set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"
+)
+
+set error=0
+%buildCMD% || set error=1
+
+if %error% == 0 (
+ set /a successCount=%successCount%+1
+) else (
+ set /a errorCount=%errorCount%+1
+)
+
+exit /b
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json new file mode 100755 index 000000000..06f7e2afd --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json @@ -0,0 +1,490 @@ +{ + "NONE": { + }, + "A8_UNORM": { + "texFormat": "DXGI_FORMAT_A8_UNORM", + "srvFormat": "DXGI_FORMAT_A8_UNORM", + "rtvFormat": "DXGI_FORMAT_A8_UNORM", + "channels": "a", + "componentType": "unorm", + "bits": { "alpha": 8 }, + "supportTest": "OnlyFL10Plus(deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_UNORM": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8" + }, + "R16G16B16A16_UNORM": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16_EXT" + }, + "R16G16B16A16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "channels": "rgba", + "componentType": "float", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16F" + }, + "R32G32B32A32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "channels": "rgba", + "componentType": "float", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32F" + }, + "B8G8R8A8_UNORM": { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_BGRA8_EXT" + }, + "BC1_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8", + "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" + }, + "BC1_RGB_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8", + "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" + }, + "BC2_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC2_UNORM", + "srvFormat": "DXGI_FORMAT_BC2_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8", + "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE" + }, + "BC3_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC3_UNORM", + "srvFormat": "DXGI_FORMAT_BC3_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8", + "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE" + }, + "D24_UNORM_S8_UINT": { + "FL10Plus": { + "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS" + }, + "FL9_3": { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT" + }, + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "channels": "ds", + "bits": { "depth": 24, "stencil": 8 }, + "glInternalFormat": "GL_DEPTH24_STENCIL8_OES" + }, + "D32_FLOAT_S8X24_UINT": { + "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT", + "channels": "ds", + "bits": { "depth": 32, "stencil": 8 }, + "glInternalFormat": "GL_DEPTH32F_STENCIL8" + }, + "D16_UNORM": { + "FL10Plus": { + "texFormat": "DXGI_FORMAT_R16_TYPELESS", + "srvFormat": "DXGI_FORMAT_R16_UNORM" + }, + "FL9_3": { + "texFormat": "DXGI_FORMAT_D16_UNORM" + }, + "dsvFormat": "DXGI_FORMAT_D16_UNORM", + "channels": "d", + "componentType": "unorm", + "bits": { "depth": 16 }, + "glInternalFormat": "GL_DEPTH_COMPONENT16" + }, + "D32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT", + "channels": "d", + "componentType": "float", + "bits": { "depth": 32 }, + "glInternalFormat": "GL_DEPTH_COMPONENT32F" + }, + "R11G11B10_FLOAT": { + "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "channels": "rgb", + "componentType": "float", + "bits": { "red": 11, "green": 11, "blue": 10 }, + "glInternalFormat": "GL_R11F_G11F_B10F" + }, + "R16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16_FLOAT", + "channels": "r", + "componentType": "float", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16F" + }, + "R16_SINT": { + "texFormat": "DXGI_FORMAT_R16_SINT", + "srvFormat": "DXGI_FORMAT_R16_SINT", + "rtvFormat": "DXGI_FORMAT_R16_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16I" + }, + "R16_UINT": { + "texFormat": "DXGI_FORMAT_R16_UINT", + "srvFormat": "DXGI_FORMAT_R16_UINT", + "rtvFormat": "DXGI_FORMAT_R16_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16UI" + }, + "R32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32_FLOAT", + "channels": "r", + "componentType": "float", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32F" + }, + "R32_SINT": { + "texFormat": "DXGI_FORMAT_R32_SINT", + "srvFormat": "DXGI_FORMAT_R32_SINT", + "rtvFormat": "DXGI_FORMAT_R32_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32I" + }, + "R32_UINT": { + "texFormat": "DXGI_FORMAT_R32_UINT", + "srvFormat": "DXGI_FORMAT_R32_UINT", + "rtvFormat": "DXGI_FORMAT_R32_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32UI" + }, + "R8_UNORM": { + "texFormat": "DXGI_FORMAT_R8_UNORM", + "srvFormat": "DXGI_FORMAT_R8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8_UNORM", + "channels": "r", + "componentType": "unorm", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8" + }, + "R8_SINT": { + "texFormat": "DXGI_FORMAT_R8_SINT", + "srvFormat": "DXGI_FORMAT_R8_SINT", + "rtvFormat": "DXGI_FORMAT_R8_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8I" + }, + "R8_UINT": { + "texFormat": "DXGI_FORMAT_R8_UINT", + "srvFormat": "DXGI_FORMAT_R8_UINT", + "rtvFormat": "DXGI_FORMAT_R8_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8UI" + }, + "R8_SNORM": { + "texFormat": "DXGI_FORMAT_R8_SNORM", + "srvFormat": "DXGI_FORMAT_R8_SNORM", + "channels": "r", + "componentType": "snorm", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8_SNORM" + }, + "R16G16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16G16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT", + "channels": "rg", + "componentType": "float", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16F" + }, + "R16G16_SINT": { + "texFormat": "DXGI_FORMAT_R16G16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16I" + }, + "R16G16_UINT": { + "texFormat": "DXGI_FORMAT_R16G16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16UI" + }, + "R32G32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32G32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT", + "channels": "rg", + "componentType": "float", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32F" + }, + "R32G32_SINT": { + "texFormat": "DXGI_FORMAT_R32G32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32I" + }, + "R32G32_UINT": { + "texFormat": "DXGI_FORMAT_R32G32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32UI" + }, + "R8G8_UNORM": { + "texFormat": "DXGI_FORMAT_R8G8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8_UNORM", + "channels": "rg", + "componentType": "unorm", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8" + }, + "R8G8_SINT": { + "texFormat": "DXGI_FORMAT_R8G8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8I" + }, + "R8G8_UINT": { + "texFormat": "DXGI_FORMAT_R8G8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8UI" + }, + "R8G8_SNORM": { + "texFormat": "DXGI_FORMAT_R8G8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8_SNORM", + "channels": "rg", + "componentType": "snorm", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8_SNORM" + }, + "R10G10B10A2_UNORM": { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 }, + "glInternalFormat": "GL_RGB10_A2" + }, + "R10G10B10A2_UINT": { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 }, + "glInternalFormat": "GL_RGB10_A2UI" + }, + "R16G16B16A16_SINT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16I" + }, + "R16G16B16A16_UINT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16UI" + }, + "R32G32B32A32_SINT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32I" + }, + "R32G32B32A32_UINT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32UI" + }, + "B5G6R5_UNORM": { + "texFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "channels": "bgr", + "componentType": "unorm", + "bits": { "red": 5, "green": 6, "blue": 5 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "B5G5R5A1_UNORM": { + "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_SINT": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8I" + }, + "R8G8B8A8_UINT": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8UI" + }, + "R8G8B8A8_SNORM": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "channels": "rgba", + "componentType": "snorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8_SNORM" + }, + "R9G9B9E5_SHAREDEXP": { + "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "channels": "rgb", + "componentType": "float", + "bits": { "red": 9, "green": 9, "blue": 9, "shared": 5 } + }, + "B4G4R4A4_UNORM": { + "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_UNORM_SRGB": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_SRGB8_ALPHA8" + }, + "R16_UNORM": { + "texFormat": "DXGI_FORMAT_R16_UNORM", + "srvFormat": "DXGI_FORMAT_R16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16_UNORM", + "channels": "r", + "componentType": "unorm", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16_EXT" + }, + "R16G16_UNORM": { + "texFormat": "DXGI_FORMAT_R16G16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16_UNORM", + "channels": "rg", + "componentType": "unorm", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16_EXT" + }, + "R16_SNORM": { + "texFormat": "DXGI_FORMAT_R16_SNORM", + "srvFormat": "DXGI_FORMAT_R16_SNORM", + "channels": "r", + "componentType": "snorm", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16_SNORM_EXT" + }, + "R16G16_SNORM": { + "texFormat": "DXGI_FORMAT_R16G16_SNORM", + "srvFormat": "DXGI_FORMAT_R16G16_SNORM", + "channels": "rg", + "componentType": "snorm", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16_SNORM_EXT" + }, + "R16G16B16A16_SNORM": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SNORM", + "channels": "rgba", + "componentType": "snorm", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16_SNORM_EXT" + } +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json new file mode 100755 index 000000000..9b2e8d9db --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json @@ -0,0 +1,74 @@ +{ + "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT", + "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT", + "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM", + "GL_COMPRESSED_R11_EAC": "R8_UNORM", + "GL_COMPRESSED_RG11_EAC": "R8G8_UNORM", + "GL_COMPRESSED_RGB8_ETC2": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGBA8_ETC2_EAC": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "NONE", + "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": "BC1_RGB_UNORM_BLOCK", + "GL_COMPRESSED_SIGNED_R11_EAC": "R8_SNORM", + "GL_COMPRESSED_SIGNED_RG11_EAC": "R8G8_SNORM", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": "R8G8B8A8_UNORM_SRGB", + "GL_COMPRESSED_SRGB8_ETC2": "R8G8B8A8_UNORM_SRGB", + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM_SRGB", + "GL_DEPTH_COMPONENT24": "D24_UNORM_S8_UINT", + "GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT", + "GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM", + "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK", + "GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT", + "GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT", + "GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM", + "GL_LUMINANCE8_EXT": "R8G8B8A8_UNORM", + "GL_LUMINANCE_ALPHA16F_EXT": "R16G16B16A16_FLOAT", + "GL_LUMINANCE_ALPHA32F_EXT": "R32G32B32A32_FLOAT", + "GL_RGB": "R8G8B8A8_UNORM", + "GL_RGB16F": "R16G16B16A16_FLOAT", + "GL_RGB16I": "R16G16B16A16_SINT", + "GL_RGB16UI": "R16G16B16A16_UINT", + "GL_RGB565": "B5G6R5_UNORM", + "GL_RGB5_A1": "B5G5R5A1_UNORM", + "GL_RGB8": "R8G8B8A8_UNORM", + "GL_RGB8I": "R8G8B8A8_SINT", + "GL_RGB8UI": "R8G8B8A8_UINT", + "GL_RGB8_SNORM": "R8G8B8A8_SNORM", + "GL_RGBA4": "B4G4R4A4_UNORM", + "GL_SRGB8": "R8G8B8A8_UNORM_SRGB", + "GL_STENCIL_INDEX8": "D24_UNORM_S8_UINT", + "GL_RGB16_EXT": "R16G16B16A16_UNORM", + "GL_RGBA16_EXT": "R16G16B16A16_UNORM", + "GL_RGB16_SNORM_EXT": "R16G16B16A16_SNORM", + "GL_RGB32F": "R32G32B32A32_FLOAT", + "GL_RGB32I": "R32G32B32A32_SINT", + "GL_RGB32UI": "R32G32B32A32_UINT" +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp new file mode 100755 index 000000000..a9dfec56b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp @@ -0,0 +1,35 @@ +// +// Copyright 2016 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. +// +// Helper routines for the D3D11 texture format table. + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "libANGLE/renderer/load_functions_table.h" + +namespace rx +{ + +namespace d3d11 +{ + +const Format &Format::getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const +{ + return (swizzleFormat == internalFormat ? *this : Format::Get(swizzleFormat, deviceCaps)); +} + +LoadFunctionMap Format::getLoadFunctions() const +{ + return GetLoadFunctionsMap(internalFormat, formatID); +} + +const angle::Format &Format::format() const +{ + return angle::Format::Get(formatID); +} + +} // namespace d3d11 + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h new file mode 100755 index 000000000..3be759f19 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h @@ -0,0 +1,105 @@ +// +// Copyright 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. +// +// texture_format_table: +// Queries for full textureFormat information based on internalFormat +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ + +#include <map> + +#include "common/angleutils.h" +#include "common/platform.h" +#include "libANGLE/renderer/Format.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" + +namespace rx +{ + +struct Renderer11DeviceCaps; + +namespace d3d11 +{ + +// For sized GL internal formats, there are several possible corresponding D3D11 formats depending +// on device capabilities. +// This structure allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and +// DSVs given a GL internal format. +struct Format final : angle::NonCopyable +{ + constexpr Format(); + constexpr Format(GLenum internalFormat, + angle::Format::ID formatID, + DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat, + DXGI_FORMAT dsvFormat, + DXGI_FORMAT blitSRVFormat, + GLenum swizzleFormat, + InitializeTextureDataFunction internalFormatInitializer); + + static const Format &Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps); + + const Format &getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const; + LoadFunctionMap getLoadFunctions() const; + const angle::Format &format() const; + + GLenum internalFormat; + angle::Format::ID formatID; + + DXGI_FORMAT texFormat; + DXGI_FORMAT srvFormat; + DXGI_FORMAT rtvFormat; + DXGI_FORMAT dsvFormat; + + DXGI_FORMAT blitSRVFormat; + + GLenum swizzleFormat; + + InitializeTextureDataFunction dataInitializerFunction; +}; + +constexpr Format::Format() + : internalFormat(GL_NONE), + formatID(angle::Format::ID::NONE), + texFormat(DXGI_FORMAT_UNKNOWN), + srvFormat(DXGI_FORMAT_UNKNOWN), + rtvFormat(DXGI_FORMAT_UNKNOWN), + dsvFormat(DXGI_FORMAT_UNKNOWN), + blitSRVFormat(DXGI_FORMAT_UNKNOWN), + swizzleFormat(GL_NONE), + dataInitializerFunction(nullptr) +{ +} + +constexpr Format::Format(GLenum internalFormat, + angle::Format::ID formatID, + DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat, + DXGI_FORMAT dsvFormat, + DXGI_FORMAT blitSRVFormat, + GLenum swizzleFormat, + InitializeTextureDataFunction internalFormatInitializer) + : internalFormat(internalFormat), + formatID(formatID), + texFormat(texFormat), + srvFormat(srvFormat), + rtvFormat(rtvFormat), + dsvFormat(dsvFormat), + blitSRVFormat(blitSRVFormat), + swizzleFormat(swizzleFormat), + dataInitializerFunction(internalFormatInitializer) +{ +} + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp new file mode 100755 index 000000000..dd9c8757f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp @@ -0,0 +1,1821 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_texture_format_table.py using data from texture_format_data.json +// +// Copyright 2016 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. +// +// texture_format_table: +// Queries for full textureFormat information based in internalFormat +// + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.h" + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" + +using namespace angle; + +namespace rx +{ + +namespace d3d11 +{ + +// static +const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) +{ + // clang-format off + switch (internalFormat) + { + case GL_ALPHA16F_EXT: + { + static constexpr Format info(GL_ALPHA16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; + } + case GL_ALPHA32F_EXT: + { + static constexpr Format info(GL_ALPHA32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_ALPHA8_EXT: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_ALPHA8_EXT, + angle::Format::ID::A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_ALPHA8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + } + case GL_BGR565_ANGLEX: + { + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) + { + static constexpr Format info(GL_BGR565_ANGLEX, + angle::Format::ID::B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G6R5_UNORM, + GL_RGBA8, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_BGR565_ANGLEX, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + } + case GL_BGR5_A1_ANGLEX: + { + static constexpr Format info(GL_BGR5_A1_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; + } + case GL_BGRA4_ANGLEX: + { + static constexpr Format info(GL_BGRA4_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; + } + case GL_BGRA8_EXT: + { + static constexpr Format info(GL_BGRA8_EXT, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; + } + case GL_COMPRESSED_R11_EAC: + { + static constexpr Format info(GL_COMPRESSED_R11_EAC, + angle::Format::ID::R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RG11_EAC: + { + static constexpr Format info(GL_COMPRESSED_RG11_EAC, + angle::Format::ID::R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGB8_ETC2: + { + static constexpr Format info(GL_COMPRESSED_RGB8_ETC2, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_COMPRESSED_RGBA8_ETC2_EAC: + { + static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, + angle::Format::ID::BC2_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC2_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, + angle::Format::ID::BC3_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC3_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGB_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SIGNED_R11_EAC: + { + static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC, + angle::Format::ID::R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_COMPRESSED_SIGNED_RG11_EAC: + { + static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC, + angle::Format::ID::R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ETC2: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; + } + case GL_DEPTH24_STENCIL8: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_DEPTH24_STENCIL8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_DEPTH24_STENCIL8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; + } + } + case GL_DEPTH32F_STENCIL8: + { + static constexpr Format info(GL_DEPTH32F_STENCIL8, + angle::Format::ID::D32_FLOAT_S8X24_UINT, + DXGI_FORMAT_R32G8X24_TYPELESS, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, + GL_RGBA32F, + nullptr); + return info; + } + case GL_DEPTH_COMPONENT16: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_DEPTH_COMPONENT16, + angle::Format::ID::D16_UNORM, + DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_R16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_DEPTH_COMPONENT16, + angle::Format::ID::D16_UNORM, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_UNKNOWN, + GL_RGBA16_EXT, + nullptr); + return info; + } + } + case GL_DEPTH_COMPONENT24: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_DEPTH_COMPONENT24, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_DEPTH_COMPONENT24, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; + } + } + case GL_DEPTH_COMPONENT32F: + { + static constexpr Format info(GL_DEPTH_COMPONENT32F, + angle::Format::ID::D32_FLOAT, + DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_DEPTH_COMPONENT32_OES: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_DEPTH_COMPONENT32_OES, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_DEPTH_COMPONENT32_OES, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; + } + } + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + { + static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, + angle::Format::ID::BC1_RGB_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_ETC1_RGB8_OES: + { + static constexpr Format info(GL_ETC1_RGB8_OES, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_LUMINANCE16F_EXT: + { + static constexpr Format info(GL_LUMINANCE16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>); + return info; + } + case GL_LUMINANCE32F_EXT: + { + static constexpr Format info(GL_LUMINANCE32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>); + return info; + } + case GL_LUMINANCE8_ALPHA8_EXT: + { + static constexpr Format info(GL_LUMINANCE8_ALPHA8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_LUMINANCE8_EXT: + { + static constexpr Format info(GL_LUMINANCE8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_LUMINANCE_ALPHA16F_EXT: + { + static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; + } + case GL_LUMINANCE_ALPHA32F_EXT: + { + static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_NONE: + { + static constexpr Format info(GL_NONE, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_R11F_G11F_B10F: + { + static constexpr Format info(GL_R11F_G11F_B10F, + angle::Format::ID::R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R11G11B10_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; + } + case GL_R16F: + { + static constexpr Format info(GL_R16F, + angle::Format::ID::R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; + } + case GL_R16I: + { + static constexpr Format info(GL_R16I, + angle::Format::ID::R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_SINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_R16UI: + { + static constexpr Format info(GL_R16UI, + angle::Format::ID::R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_UINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_R16_EXT: + { + static constexpr Format info(GL_R16_EXT, + angle::Format::ID::R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_R16_SNORM_EXT: + { + static constexpr Format info(GL_R16_SNORM_EXT, + angle::Format::ID::R16_SNORM, + DXGI_FORMAT_R16_SNORM, + DXGI_FORMAT_R16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; + } + case GL_R32F: + { + static constexpr Format info(GL_R32F, + angle::Format::ID::R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_R32I: + { + static constexpr Format info(GL_R32I, + angle::Format::ID::R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_SINT, + GL_RGBA32I, + nullptr); + return info; + } + case GL_R32UI: + { + static constexpr Format info(GL_R32UI, + angle::Format::ID::R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_UINT, + GL_RGBA32I, + nullptr); + return info; + } + case GL_R8: + { + static constexpr Format info(GL_R8, + angle::Format::ID::R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_R8I: + { + static constexpr Format info(GL_R8I, + angle::Format::ID::R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SINT, + GL_RGBA8I, + nullptr); + return info; + } + case GL_R8UI: + { + static constexpr Format info(GL_R8UI, + angle::Format::ID::R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UINT, + GL_RGBA8I, + nullptr); + return info; + } + case GL_R8_SNORM: + { + static constexpr Format info(GL_R8_SNORM, + angle::Format::ID::R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_RG16F: + { + static constexpr Format info(GL_RG16F, + angle::Format::ID::R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; + } + case GL_RG16I: + { + static constexpr Format info(GL_RG16I, + angle::Format::ID::R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_SINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_RG16UI: + { + static constexpr Format info(GL_RG16UI, + angle::Format::ID::R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_UINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_RG16_EXT: + { + static constexpr Format info(GL_RG16_EXT, + angle::Format::ID::R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_RG16_SNORM_EXT: + { + static constexpr Format info(GL_RG16_SNORM_EXT, + angle::Format::ID::R16G16_SNORM, + DXGI_FORMAT_R16G16_SNORM, + DXGI_FORMAT_R16G16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; + } + case GL_RG32F: + { + static constexpr Format info(GL_RG32F, + angle::Format::ID::R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_RG32I: + { + static constexpr Format info(GL_RG32I, + angle::Format::ID::R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_SINT, + GL_RGBA32I, + nullptr); + return info; + } + case GL_RG32UI: + { + static constexpr Format info(GL_RG32UI, + angle::Format::ID::R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_UINT, + GL_RGBA32I, + nullptr); + return info; + } + case GL_RG8: + { + static constexpr Format info(GL_RG8, + angle::Format::ID::R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_RG8I: + { + static constexpr Format info(GL_RG8I, + angle::Format::ID::R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SINT, + GL_RGBA8I, + nullptr); + return info; + } + case GL_RG8UI: + { + static constexpr Format info(GL_RG8UI, + angle::Format::ID::R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UINT, + GL_RGBA8I, + nullptr); + return info; + } + case GL_RG8_SNORM: + { + static constexpr Format info(GL_RG8_SNORM, + angle::Format::ID::R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_RGB: + { + static constexpr Format info(GL_RGB, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_RGB10_A2: + { + static constexpr Format info(GL_RGB10_A2, + angle::Format::ID::R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R10G10B10A2_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_RGB10_A2UI: + { + static constexpr Format info(GL_RGB10_A2UI, + angle::Format::ID::R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R10G10B10A2_UINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_RGB16F: + { + static constexpr Format info(GL_RGB16F, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>); + return info; + } + case GL_RGB16I: + { + static constexpr Format info(GL_RGB16I, + angle::Format::ID::R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SINT, + GL_RGBA16I, + Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>); + return info; + } + case GL_RGB16UI: + { + static constexpr Format info(GL_RGB16UI, + angle::Format::ID::R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UINT, + GL_RGBA16UI, + Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>); + return info; + } + case GL_RGB16_EXT: + { + static constexpr Format info(GL_RGB16_EXT, + angle::Format::ID::R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + GL_RGBA16_EXT, + Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>); + return info; + } + case GL_RGB16_SNORM_EXT: + { + static constexpr Format info(GL_RGB16_SNORM_EXT, + angle::Format::ID::R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SNORM, + GL_RGBA16_SNORM_EXT, + Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>); + return info; + } + case GL_RGB32F: + { + static constexpr Format info(GL_RGB32F, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>); + return info; + } + case GL_RGB32I: + { + static constexpr Format info(GL_RGB32I, + angle::Format::ID::R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_SINT, + GL_RGBA32I, + Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>); + return info; + } + case GL_RGB32UI: + { + static constexpr Format info(GL_RGB32UI, + angle::Format::ID::R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_UINT, + GL_RGBA32UI, + Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>); + return info; + } + case GL_RGB565: + { + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) + { + static constexpr Format info(GL_RGB565, + angle::Format::ID::B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G6R5_UNORM, + GL_RGBA8, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_RGB565, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + } + case GL_RGB5_A1: + { + if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)) + { + static constexpr Format info(GL_RGB5_A1, + angle::Format::ID::B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G5R5A1_UNORM, + GL_RGBA8, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_RGB5_A1, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + } + case GL_RGB8: + { + static constexpr Format info(GL_RGB8, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_RGB8I: + { + static constexpr Format info(GL_RGB8I, + angle::Format::ID::R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SINT, + GL_RGBA8I, + Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>); + return info; + } + case GL_RGB8UI: + { + static constexpr Format info(GL_RGB8UI, + angle::Format::ID::R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UINT, + GL_RGBA8UI, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>); + return info; + } + case GL_RGB8_SNORM: + { + static constexpr Format info(GL_RGB8_SNORM, + angle::Format::ID::R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SNORM, + GL_RGBA8_SNORM, + Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>); + return info; + } + case GL_RGB9_E5: + { + static constexpr Format info(GL_RGB9_E5, + angle::Format::ID::R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + GL_RGBA16F_EXT, + nullptr); + return info; + } + case GL_RGBA: + { + static constexpr Format info(GL_RGBA, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_RGBA16F: + { + static constexpr Format info(GL_RGBA16F, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; + } + case GL_RGBA16I: + { + static constexpr Format info(GL_RGBA16I, + angle::Format::ID::R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_RGBA16UI: + { + static constexpr Format info(GL_RGBA16UI, + angle::Format::ID::R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UINT, + GL_RGBA16UI, + nullptr); + return info; + } + case GL_RGBA16_EXT: + { + static constexpr Format info(GL_RGBA16_EXT, + angle::Format::ID::R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_RGBA16_SNORM_EXT: + { + static constexpr Format info(GL_RGBA16_SNORM_EXT, + angle::Format::ID::R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; + } + case GL_RGBA32F: + { + static constexpr Format info(GL_RGBA32F, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; + } + case GL_RGBA32I: + { + static constexpr Format info(GL_RGBA32I, + angle::Format::ID::R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_SINT, + GL_RGBA32I, + nullptr); + return info; + } + case GL_RGBA32UI: + { + static constexpr Format info(GL_RGBA32UI, + angle::Format::ID::R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_UINT, + GL_RGBA32UI, + nullptr); + return info; + } + case GL_RGBA4: + { + if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)) + { + static constexpr Format info(GL_RGBA4, + angle::Format::ID::B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B4G4R4A4_UNORM, + GL_RGBA4, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_RGBA4, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + } + case GL_RGBA8: + { + static constexpr Format info(GL_RGBA8, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_RGBA8I: + { + static constexpr Format info(GL_RGBA8I, + angle::Format::ID::R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SINT, + GL_RGBA8I, + nullptr); + return info; + } + case GL_RGBA8UI: + { + static constexpr Format info(GL_RGBA8UI, + angle::Format::ID::R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UINT, + GL_RGBA8UI, + nullptr); + return info; + } + case GL_RGBA8_SNORM: + { + static constexpr Format info(GL_RGBA8_SNORM, + angle::Format::ID::R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_SRGB8: + { + static constexpr Format info(GL_SRGB8, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>); + return info; + } + case GL_SRGB8_ALPHA8: + { + static constexpr Format info(GL_SRGB8_ALPHA8, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; + } + case GL_STENCIL_INDEX8: + { + if (OnlyFL10Plus(deviceCaps)) + { + static constexpr Format info(GL_STENCIL_INDEX8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; + } + else + { + static constexpr Format info(GL_STENCIL_INDEX8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; + } + } + + default: + break; + } + // clang-format on + + UNREACHABLE(); + static constexpr Format defaultInfo; + return defaultInfo; +} + +} // namespace d3d11 + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h new file mode 100755 index 000000000..bffea6af9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h @@ -0,0 +1,77 @@ +// +// Copyright 2016 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. +// +// Helper routines for the D3D11 texture format table. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +namespace d3d11 +{ + +using FormatSupportFunction = bool (*)(const Renderer11DeviceCaps &); + +inline bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0); +} + +inline bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3); +} + +inline bool SupportsFormat(DXGI_FORMAT format, const Renderer11DeviceCaps &deviceCaps) +{ + // Must support texture, SRV and RTV support + UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE | + D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | + D3D11_FORMAT_SUPPORT_RENDER_TARGET; + + if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2) + { + mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } + + bool fullSupport = false; + if (format == DXGI_FORMAT_B5G6R5_UNORM) + { + // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but + // check anyway. + mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; + fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport); + } + else if (format == DXGI_FORMAT_B4G4R4A4_UNORM) + { + fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport); + } + else if (format == DXGI_FORMAT_B5G5R5A1_UNORM) + { + fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport); + } + else + { + UNREACHABLE(); + return false; + } + + // This means that ANGLE would like to use the entry in the map if the inputted DXGI format + // *IS* supported. + // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if + // DXGI_FORMAT_B5G5R5A1 is supported. + // In this case, we should only return 'true' if the format *IS* supported. + return fullSupport; +} + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp new file mode 100755 index 000000000..ddfd58c74 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp @@ -0,0 +1,242 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs. + +#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include "common/debug.h" + +#include <initguid.h> + +#ifdef HAS_DIRECT_COMPOSITION +#include <dcomp.h> +#endif // HAS_DIRECT_COMPOSITION + +namespace rx +{ + +NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window, + bool hasAlpha, + bool directComposition) + : NativeWindow11(window), + mDirectComposition(directComposition), + mHasAlpha(hasAlpha) + +#ifdef HAS_DIRECT_COMPOSITION + + , mDevice(nullptr), + mCompositionTarget(nullptr), + mVisual(nullptr) + +#endif // HAS_DIRECT_COMPOSITION + +{ +} + +NativeWindow11Win32::~NativeWindow11Win32() +{ + +#ifdef HAS_DIRECT_COMPOSITION + + SafeRelease(mCompositionTarget); + SafeRelease(mDevice); + SafeRelease(mVisual); + +#endif // HAS_DIRECT_COMPOSITION + +} + +bool NativeWindow11Win32::initialize() +{ + return true; +} + +bool NativeWindow11Win32::getClientRect(LPRECT rect) const +{ + return GetClientRect(getNativeWindow(), rect) == TRUE; +} + +bool NativeWindow11Win32::isIconic() const +{ + return IsIconic(getNativeWindow()) == TRUE; +} + +#ifdef ANGLE_ENABLE_D3D11 +HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + IDXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + if (mDirectComposition) + { +#ifdef HAS_DIRECT_COMPOSITION + HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll")); + if (!dcomp) + { + return E_INVALIDARG; + } + + typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)( + IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); + PFN_DCOMPOSITION_CREATE_DEVICE createDComp = + reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>( + GetProcAddress(dcomp, "DCompositionCreateDevice")); + if (!createDComp) + { + return E_INVALIDARG; + } + + if (!mDevice) + { + IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device); + HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice), + reinterpret_cast<void **>(&mDevice)); + SafeRelease(dxgiDevice); + + if (FAILED(result)) + { + return result; + } + } + + if (!mCompositionTarget) + { + HRESULT result = + mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget); + if (FAILED(result)) + { + return result; + } + } + + if (!mVisual) + { + HRESULT result = mDevice->CreateVisual(&mVisual); + if (FAILED(result)) + { + return result; + } + } + + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory); + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT; + swapChainDesc.BufferCount = 2; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = + mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = 0; + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = + factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + *swapChain = static_cast<IDXGISwapChain *>(swapChain1); + } + mVisual->SetContent(swapChain1); + mCompositionTarget->SetRoot(mVisual); + SafeRelease(factory2); + return result; +#else // HAS_DIRECT_COMPOSITION + return E_INVALIDARG; +#endif // HAS_DIRECT_COMPOSITION + } + + // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a + // DXGI_SWAP_EFFECT_SEQUENTIAL swap chain. + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory); + if (factory2 != nullptr) + { + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 1; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapChainDesc.Flags = 0; + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc, + nullptr, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + *swapChain = static_cast<IDXGISwapChain *>(swapChain1); + } + SafeRelease(factory2); + return result; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = getNativeWindow(); + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); + if (SUCCEEDED(result)) + { + factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + } + return result; +} +#endif // ANGLE_ENABLE_D3D11 + +void NativeWindow11Win32::commitChange() +{ + +#ifdef HAS_DIRECT_COMPOSITION + + if (mDevice) + { + mDevice->Commit(); + } + +#endif // HAS_DIRECT_COMPOSITION + +} + +// static +bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h new file mode 100755 index 000000000..8a9ebe800 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11Win32.h: Implementation of NativeWindow11 using win32 window APIs. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" + +typedef interface IDCompositionDevice IDCompositionDevice; +typedef interface IDCompositionTarget IDCompositionTarget; +typedef interface IDCompositionVisual IDCompositionVisual; + +namespace rx +{ + +class NativeWindow11Win32 : public NativeWindow11 +{ + public: + NativeWindow11Win32(EGLNativeWindowType window, bool hasAlpha, bool directComposition); + ~NativeWindow11Win32() override; + + bool initialize() override; + bool getClientRect(LPRECT rect) const override; + bool isIconic() const override; + + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + IDXGISwapChain **swapChain) override; + + void commitChange() override; + + static bool IsValidNativeWindow(EGLNativeWindowType window); + + private: + bool mDirectComposition; + bool mHasAlpha; + IDCompositionDevice *mDevice; + IDCompositionTarget *mCompositionTarget; + IDCompositionVisual *mVisual; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp new file mode 100755 index 000000000..0211e6887 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp @@ -0,0 +1,229 @@ +// +// Copyright (c) 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. +// + +// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" + +#include <windows.graphics.display.h> + +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +CoreWindowNativeWindow::~CoreWindowNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + SIZE swapChainSize = {}; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified); + if (FAILED(result)) + { + return false; + } + + if (!mSwapChainScaleSpecified) + { + // Default value for the scale is 1.0f + mSwapChainScale = 1.0f; + } + + // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified + if (mSwapChainScaleSpecified && mSwapChainSizeSpecified) + { + ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty."); + return false; + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mCoreWindow); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output occurs automatically because if + // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. + if (mSwapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + } + else + { + Size coreWindowSize; + result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize); + + if (SUCCEEDED(result)) + { + mClientRect = clientRect(coreWindowSize); + } + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool CoreWindowNativeWindow::registerForSizeChangeEvents() +{ + ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler; + HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + if (SUCCEEDED(result)) + { + result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void CoreWindowNativeWindow::unregisterForSizeChangeEvents() +{ + if (mCoreWindow) + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } + mSizeChangedEventToken.value = 0; +} + +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, + IDXGIFactory2 *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + IDXGISwapChain1 **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + if (SUCCEEDED(result)) + { + result = newSwapChain.CopyTo(swapChain); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, + const RECT &clientRect) +{ + // We don't need to do any additional work to scale CoreWindow swapchains. + // Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work. + return S_OK; +} + +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow, + Size *windowSize) +{ + ABI::Windows::Foundation::Rect bounds; + HRESULT result = coreWindow->get_Bounds(&bounds); + if (SUCCEEDED(result)) + { + *windowSize = { ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; + } + + return result; +} + +static float GetLogicalDpi() +{ + ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties; + + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf()))) + { + float dpi = 96.0f; + if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi))) + { + return dpi; + } + } + + // Return 96 dpi as a default if display properties cannot be obtained. + return 96.0f; +} + +float ConvertDipsToPixels(float dips) +{ + static const float dipsPerInch = 96.0f; + return dips * GetLogicalDpi() / dipsPerInch; +} +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h new file mode 100755 index 000000000..d43bf0ba5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 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. +// + +// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + +#include <memory> + +#include <EGL/eglplatform.h> + +typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; + +namespace rx +{ +float ConvertDipsToPixels(float dips); + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow> +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory2 *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + IDXGISwapChain1 **swapChain) override; + + protected: + HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; + + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + + private: + ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; +}; + +[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] +class CoreWindowSizeChangedHandler : + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler> +{ + public: + CoreWindowSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // IWindowSizeChangedEventHandler + IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + ABI::Windows::Foundation::Size windowSize; + if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) + { + Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width), + ConvertDipsToPixels(windowSize.Height)}; + host->setNewClientSize(windowSizeInPixels); + } + } + + return S_OK; + } + + private: + std::weak_ptr<InspectableNativeWindow> mHost; +}; + +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow, + Size *windowSize); +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp new file mode 100755 index 000000000..6b5ae14c5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp @@ -0,0 +1,356 @@ +// +// Copyright (c) 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. +// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP +// to ensure that the proper defines are set when including additional +// headers which rely on Windows Store specific configuration. +// This would normally be defined already but this unittest exe is compiled +// as a desktop application which results in WINAPI_FAMILY being +// set to WINAPI_FAMILY_DESKTOP_APP +#undef WINAPI_FAMILY +#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include <angle_windowsstore.h> + +using namespace rx; +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::System; + +namespace +{ + +// Mock Generic interfaces which are NOT ICoreWindow or +// IPropertySet +MIDL_INTERFACE("A4D67D0A-0E7F-4DF7-918B-7A1395413AF2") +IAmInspectable : public IInspectable +{ +}; + +class GenericIInspectable : public RuntimeClass < + RuntimeClassFlags<WinRtClassicComMix>, + IAmInspectable > +{ +}; + +MIDL_INTERFACE("3CBCFE7A-E000-4094-B2D2-B7C9A4D67A2C") +IAmUnknown : public IUnknown +{ +}; + +class GenericIUnknown : public RuntimeClass < + RuntimeClassFlags<ClassicCom>, + IAmUnknown > +{ +}; + +// Mock ICoreWindow +class MockCoreWindow : public ABI::Windows::UI::Core::ICoreWindow +{ + public: + // IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) + { + *ppvObject = NULL; + + if (IsEqualIID(IID_IUnknown, riid)) + { + *ppvObject = static_cast<IUnknown*>(this); + return S_OK; + } + + if (IsEqualIID(IID_IInspectable, riid)) + { + *ppvObject = static_cast<IInspectable*>(this); + return S_OK; + } + + if (IsEqualIID(IID_ICoreWindow, riid)) + { + *ppvObject = static_cast<ABI::Windows::UI::Core::ICoreWindow*>(this); + return S_OK; + } + + return E_NOINTERFACE; + } + + STDMETHOD_(ULONG, AddRef)(){ return 1; } + STDMETHOD_(ULONG, Release)(){ return 1; } + + // IInspectable + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *)); + + // ICoreWindow + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AutomationHostProvider, HRESULT(IInspectable **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Bounds, HRESULT(Rect *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CustomProperties, HRESULT(IPropertySet **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Dispatcher, HRESULT(ICoreDispatcher **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(CoreWindowFlowDirection *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(CoreWindowFlowDirection)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsInputEnabled, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsInputEnabled, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCursor, HRESULT(ICoreCursor**)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_PointerCursor, HRESULT(ICoreCursor*)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerPosition, HRESULT(Point*)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visible, HRESULT(boolean *)); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Activate, HRESULT()); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Close , HRESULT()); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetAsyncKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*)); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT()); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, SetPointerCapture, HRESULT()); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Activated, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Activated, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_AutomationProviderRequested, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_AutomationProviderRequested, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CharacterReceived, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCharacterReceivedEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CharacterReceived, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Closed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCoreWindowEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Closed, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_InputEnabled, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CInputEnabledEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_InputEnabled, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_TouchHitTesting, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CTouchHitTestingEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_TouchHitTesting, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_VisibilityChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs*, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_VisibilityChanged, HRESULT(EventRegistrationToken)); +}; + +HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap) +{ + HRESULT result = S_OK; + ComPtr<IPropertySet> propertySet; + ComPtr<IActivationFactory> propertySetFactory; + result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertySetFactory->ActivateInstance(&propertySet); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertySet.CopyTo(propertyMap); + EXPECT_HRESULT_SUCCEEDED(result); + + return result; +} + +HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics) +{ + ComPtr<IPropertyValueStatics> propertyValueStatics; + HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertyValueStatics.CopyTo(propertyStatics); + EXPECT_HRESULT_SUCCEEDED(result); + + return result; +} + +HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable) +{ + boolean propertyReplaced = false; + return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced); +} + +void expectNativeWindowInitCalls(MockCoreWindow &coreWindow, bool expectBounds) +{ + if (expectBounds) + { + EXPECT_CALL(coreWindow, get_Bounds(testing::_)).Times(1); + } + + EXPECT_CALL(coreWindow, add_SizeChanged(testing::_, testing::_)).Times(1); + EXPECT_CALL(coreWindow, remove_SizeChanged(testing::_)).Times(1); +} + +TEST(NativeWindowTest, NativeWindowNull) +{ + NativeWindow nativeWindow(nullptr); + EXPECT_FALSE(nativeWindow.initialize()); +} + +TEST(NativeWindowTest, NativeWindowBadInspectable) +{ + ComPtr<IAmInspectable> notCoreWindow = Make<GenericIInspectable>(); + NativeWindow nativeWindow(notCoreWindow.Get()); + EXPECT_FALSE(nativeWindow.initialize()); +} + +TEST(NativeWindowTest, NativeWindowNotInspectable) +{ + ComPtr<IAmUnknown> notIInspectable = Make<GenericIUnknown>(); + NativeWindow nativeWindow((IInspectable*)notIInspectable.Get()); + EXPECT_FALSE(nativeWindow.initialize()); +} + +TEST(NativeWindowTest, NativeWindowValidCoreWindow) +{ + MockCoreWindow mockCoreWindow; + expectNativeWindowInitCalls(mockCoreWindow, true); + NativeWindow nativeWindow(&mockCoreWindow); + EXPECT_TRUE(nativeWindow.initialize()); +} + +TEST(NativeWindowTest, NativeWindowValidCoreWindowInPropertySet) +{ + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockCoreWindow mockCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + + // Add the CoreWindow to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, &mockCoreWindow)); + + expectNativeWindowInitCalls(mockCoreWindow, true); + NativeWindow nativeWindow(propertySet.Get()); + EXPECT_TRUE(nativeWindow.initialize()); + } + CoUninitialize(); +} + +TEST(NativeWindowTest, NativeWindowMissingCoreWindowInPropertySet) +{ + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockCoreWindow mockCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + + NativeWindow nativeWindow(propertySet.Get()); + EXPECT_FALSE(nativeWindow.initialize()); + } + CoUninitialize(); +} + +// Tests that the scale property works as expected in a property set with a SwapChainPanel +class CoreWindowScaleTest : public testing::TestWithParam<std::pair<float, bool>> +{ +}; + +TEST_P(CoreWindowScaleTest, ValidateScale) +{ + float scale = GetParam().first; + bool expectedResult = GetParam().second; + + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockCoreWindow mockCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + ComPtr<IPropertyValueStatics> propertyValueStatics; + ComPtr<IPropertyValue> singleValue; + + // Create a simple property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow))); + + // Add a valid scale factor to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get()))); + + // Check native window init status and calls to the mock swapchainpanel + NativeWindow nativeWindow(propertySet.Get()); + if (expectedResult) + { + expectNativeWindowInitCalls(mockCoreWindow, true); + } + + EXPECT_EQ(nativeWindow.initialize(), expectedResult); + } + CoUninitialize(); +} + +typedef std::pair<float, bool> scaleValidPair; +static const scaleValidPair scales[] = { scaleValidPair(1.0f, true), + scaleValidPair(0.5f, true), + scaleValidPair(0.0f, false), + scaleValidPair(0.01f, true), + scaleValidPair(2.00f, true) }; + +INSTANTIATE_TEST_CASE_P(NativeWindowTest, + CoreWindowScaleTest, + testing::ValuesIn(scales)); + +// Tests that the size property works as expected in a property set with a SwapChainPanel +class CoreWindowSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>> +{ +}; + +TEST_P(CoreWindowSizeTest, ValidateSize) +{ + Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) }; + bool expectedResult = std::get<2>(GetParam()); + + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockCoreWindow mockCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + ComPtr<IPropertyValueStatics> propertyValueStatics; + ComPtr<IPropertyValue> sizeValue; + + // Create a simple property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow))); + + // Add a valid size to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get()))); + + // Check native window init status and calls to the mock swapchainpanel + NativeWindow nativeWindow(propertySet.Get()); + if (expectedResult) + { + expectNativeWindowInitCalls(mockCoreWindow, false); + } + + EXPECT_EQ(nativeWindow.initialize(), expectedResult); + } + CoUninitialize(); +} + +typedef std::tuple<float, float, bool> sizeValidPair; +static const sizeValidPair sizes[] = { sizeValidPair( 800, 480, true), + sizeValidPair( 0, 480, false), + sizeValidPair( 800, 0, false), + sizeValidPair( 0, 0, false) }; + +INSTANTIATE_TEST_CASE_P(NativeWindowTest, + CoreWindowSizeTest, + testing::ValuesIn(sizes)); + +} // namespace diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp new file mode 100755 index 000000000..c7fcf8634 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -0,0 +1,276 @@ +// +// Copyright (c) 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. +// + +// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +namespace rx +{ + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin; + if (SUCCEEDED(win.As(&coreWin))) + { + if (coreWindow != nullptr) + { + *coreWindow = coreWin.Detach(); + } + return true; + } + + return false; +} + +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel; + if (SUCCEEDED(win.As(&panel))) + { + if (swapChainPanel != nullptr) + { + *swapChainPanel = panel.Detach(); + } + return true; + } + + return false; +} + +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> props = window; + ComPtr<IPropertySet> propSet; + ComPtr<IInspectable> nativeWindow; + ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap; + boolean hasEglNativeWindowPropertyKey = false; + + HRESULT result = props.As(&propSet); + if (SUCCEEDED(result)) + { + result = propSet.As(&propMap); + } + + // Look for the presence of the EGLNativeWindowType in the property set + if (SUCCEEDED(result)) + { + result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); + } + + // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is + // considered invalid. + if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) + { + ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + return false; + } + + // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType + if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) + { + result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); + } + + if (SUCCEEDED(result)) + { + if (propertySet != nullptr) + { + result = propSet.CopyTo(propertySet); + } + } + + if (SUCCEEDED(result)) + { + if (eglNativeWindow != nullptr) + { + result = nativeWindow.CopyTo(eglNativeWindow); + } + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +// Retrieve an optional property from a property set +HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, + boolean *hasKey, + ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue) +{ + if (!propertyMap || !hasKey) + { + return E_INVALIDARG; + } + + // Assume that the value does not exist + *hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey); + if (SUCCEEDED(result) && !(*hasKey)) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + return result; +} + +// Attempts to read an optional SIZE property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated +// S_OK, valueExists == false - optional SIZE value was not found +// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Size) +// * Invalid property value (width/height must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, SIZE *value, bool *valueExists) +{ + ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + if (!propertyMap || !value || !valueExists) + { + return E_INVALIDARG; + } + + // Assume that the value does not exist + *valueExists = false; + *value = { 0, 0 }; + + HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue); + if (SUCCEEDED(result) && hasKey) + { + result = propertyValue->get_Type(&propertyType); + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + } + + return result; +} + +// Attempts to read an optional float property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Single. This function validates the Single value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional Single value was successfully retrieved and validated +// S_OK, valueExists == false - optional Single value was not found +// E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Single) +// * Invalid property value (must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, float *value, bool *valueExists) +{ + ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + float scaleValue = 0.0f; + boolean hasKey = false; + + if (!propertyMap || !value || !valueExists) + { + return E_INVALIDARG; + } + + // Assume that the value does not exist + *valueExists = false; + *value = 0.0f; + + HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue); + if (SUCCEEDED(result) && hasKey) + { + result = propertyValue->get_Type(&propertyType); + + // Check if the expected Scale property is of PropertyType_Single type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single) + { + if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f)) + { + // A valid property value exists + *value = scaleValue; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid scale was set + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Single + result = E_INVALIDARG; + } + } + + return result; +} + +RECT InspectableNativeWindow::clientRect(const Size &size) +{ + // We don't have to check if a swapchain scale was specified here; the default value is 1.0f + // which will have no effect. + return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)}; +} +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h new file mode 100755 index 000000000..3e67269f3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 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. +// + +// InspectableNativeWindow.h: Host specific implementation interface for +// managing IInspectable native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include "angle_windowsstore.h" + +#include <EGL/eglplatform.h> + +#include <windows.applicationmodel.core.h> +#include <windows.ui.xaml.h> +#include <windows.ui.xaml.media.dxinterop.h> +#include <wrl.h> +#include <wrl/wrappers/corewrappers.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +class InspectableNativeWindow +{ + public: + InspectableNativeWindow() : + mSupportsSwapChainResize(true), + mSwapChainSizeSpecified(false), + mSwapChainScaleSpecified(false), + mSwapChainScale(1.0f), + mClientRectChanged(false), + mClientRect({0,0,0,0}), + mNewClientRect({0,0,0,0}) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + + virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory2 *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + IDXGISwapChain1 **swapChain) = 0; + + bool getClientRect(RECT *rect) + { + if (mClientRectChanged) + { + mClientRect = mNewClientRect; + } + + *rect = mClientRect; + + return true; + } + + // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of ANGLE. + void setNewClientSize(const Size &newWindowSize) + { + // If the client doesn't support swapchain resizing then we should have already unregistered from size change handler + ASSERT(mSupportsSwapChainResize); + + if (mSupportsSwapChainResize) + { + // If the swapchain size was specified then we should ignore this call too + if (!mSwapChainSizeSpecified) + { + mNewClientRect = clientRect(newWindowSize); + mClientRectChanged = true; + + // If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size + if (mSwapChainScaleSpecified) + { + scaleSwapChain(newWindowSize, mNewClientRect); + } + } + + // Even if the swapchain size was fixed, the window might have changed size. + // In this case, we should recalculate the scale matrix to account for the new window size + if (mSwapChainSizeSpecified) + { + scaleSwapChain(newWindowSize, mClientRect); + } + } + } + + protected: + virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0; + RECT clientRect(const Size &size); + + bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method + bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified + bool mSwapChainScaleSpecified; // If an EGLRenderResolutionScaleProperty was specified + float mSwapChainScale; // The scale value specified by the EGLRenderResolutionScaleProperty property + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; + + EventRegistrationToken mSizeChangedEventToken; +}; + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr); +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr); +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); + +HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, + boolean *hasKey, + ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue); + +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, SIZE *value, bool *valueExists); + +HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, + const wchar_t *propertyName, float *value, bool *valueExists); +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp new file mode 100755 index 000000000..a5ce4ca68 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11WinRT.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h" + +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +namespace rx +{ +NativeWindow11WinRT::NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha) + : NativeWindow11(window), mHasAlpha(hasAlpha) +{ +} + +bool NativeWindow11WinRT::initialize() +{ + EGLNativeWindowType window = getNativeWindow(); + + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet; + ComPtr<IInspectable> eglNativeWindow; + if (IsEGLConfiguredPropertySet(window, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + window = eglNativeWindow.Get(); + } + + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel; + if (IsCoreWindow(window, &coreWindow)) + { + mImpl = std::make_shared<CoreWindowNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(window, propertySet.Get()); + } + } + else if (IsSwapChainPanel(window, &swapChainPanel)) + { + mImpl = std::make_shared<SwapChainPanelNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(window, propertySet.Get()); + } + } + else + { + ERR( + "Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include " + "ICoreWindow, ISwapChainPanel and IPropertySet"); + } + + return false; +} + +bool NativeWindow11WinRT::getClientRect(LPRECT rect) const +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +bool NativeWindow11WinRT::isIconic() const +{ + return false; +} + +HRESULT NativeWindow11WinRT::createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + IDXGISwapChain **swapChain) +{ + if (mImpl) + { + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory); + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = + mImpl->createSwapChain(device, factory2, format, width, height, mHasAlpha, &swapChain1); + SafeRelease(factory2); + *swapChain = static_cast<IDXGISwapChain *>(swapChain1); + return result; + } + + return E_UNEXPECTED; +} + +void NativeWindow11WinRT::commitChange() +{ +} + +// static +bool NativeWindow11WinRT::IsValidNativeWindow(EGLNativeWindowType window) +{ + // A Valid EGLNativeWindowType IInspectable can only be: + // + // ICoreWindow + // ISwapChainPanel + // IPropertySet + // + // Anything else will be rejected as an invalid IInspectable. + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h new file mode 100755 index 000000000..996fd3a10 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11WinRT.h: NativeWindow base class for managing IInspectable native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" + +#include <memory> +#include <windows.applicationmodel.core.h> +#include <wrl.h> +#include <wrl/wrappers/corewrappers.h> + +namespace rx +{ +class InspectableNativeWindow; + +class NativeWindow11WinRT : public NativeWindow11 +{ + public: + NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha); + + bool initialize() override; + bool getClientRect(LPRECT rect) const override; + bool isIconic() const override; + + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + IDXGISwapChain **swapChain) override; + + void commitChange() override; + + static bool IsValidNativeWindow(EGLNativeWindowType window); + + private: + bool mHasAlpha; + std::shared_ptr<InspectableNativeWindow> mImpl; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp new file mode 100755 index 000000000..1dae1ad7d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp @@ -0,0 +1,355 @@ +// +// Copyright (c) 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. +// + +// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +#include <algorithm> +#include <math.h> + +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::Xaml; +using namespace Microsoft::WRL; + +namespace rx +{ +SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +template <typename T> +struct AddFtmBase +{ + typedef Implements<RuntimeClassFlags<ClassicCom>, T, FtmBase> Type; +}; + +template <typename CODE> +HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher) +{ + ComPtr<IAsyncAction> asyncAction; + HRESULT result = S_OK; + + boolean hasThreadAccess; + result = dispatcher->get_HasThreadAccess(&hasThreadAccess); + if (FAILED(result)) + { + return result; + } + + if (hasThreadAccess) + { + return code(); + } + else + { + Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); + if (!waitEvent.IsValid()) + { + return E_FAIL; + } + + HRESULT codeResult = E_FAIL; + auto handler = + Callback<AddFtmBase<IDispatchedHandler>::Type>([&codeResult, &code, &waitEvent] + { + codeResult = code(); + SetEvent(waitEvent.Get()); + return S_OK; + }); + + result = dispatcher->RunAsync(CoreDispatcherPriority_Normal, handler.Get(), + asyncAction.GetAddressOf()); + if (FAILED(result)) + { + return result; + } + + auto waitResult = WaitForSingleObjectEx(waitEvent.Get(), 10 * 1000, true); + if (waitResult != WAIT_OBJECT_0) + { + // Wait 10 seconds before giving up. At this point, the application is in an + // unrecoverable state (probably deadlocked). We therefore terminate the application + // entirely. This also prevents stack corruption if the async operation is eventually + // run. + ERR("Timeout waiting for async action on UI thread. The UI thread might be blocked."); + std::terminate(); + return E_FAIL; + } + + return codeResult; + } +} + +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + SIZE swapChainSize = {}; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified); + if (FAILED(result)) + { + return false; + } + + if (!mSwapChainScaleSpecified) + { + // Default value for the scale is 1.0f + mSwapChainScale = 1.0f; + } + + // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified + if (mSwapChainScaleSpecified && mSwapChainSizeSpecified) + { + ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty."); + return false; + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mSwapChainPanel); + } + + ComPtr<IDependencyObject> swapChainPanelDependencyObject; + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelDependencyObject); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelDependencyObject->get_Dispatcher( + mSwapChainPanelDispatcher.GetAddressOf()); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output needs to be handled by the + // host for swapchain panels even though the scaling mode setting + // DXGI_SCALING_STRETCH is configured on the swapchain. + if (mSwapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + } + else + { + Size swapChainPanelSize; + result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, + &swapChainPanelSize); + + if (SUCCEEDED(result)) + { + // Update the client rect to account for any swapchain scale factor + mClientRect = clientRect(swapChainPanelSize); + } + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() +{ + ComPtr<ISizeChangedEventHandler> sizeChangedHandler; + ComPtr<IFrameworkElement> frameworkElement; + HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&frameworkElement); + } + + if (SUCCEEDED(result)) + { + result = RunOnUIThread( + [this, frameworkElement, sizeChangedHandler] + { + return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), + &mSizeChangedEventToken); + }, + mSwapChainPanelDispatcher); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() +{ + ComPtr<IFrameworkElement> frameworkElement; + if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + { + RunOnUIThread( + [this, frameworkElement] + { + return frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + }, + mSwapChainPanelDispatcher); + } + + mSizeChangedEventToken.value = 0; +} + +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, + IDXGIFactory2 *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + IDXGISwapChain1 **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = + containsAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + ComPtr<ISwapChainPanelNative> swapChainPanelNative; + Size currentPanelSize = {}; + + HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelNative); + } + + if (SUCCEEDED(result)) + { + result = RunOnUIThread( + [swapChainPanelNative, newSwapChain] + { + return swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + }, + mSwapChainPanelDispatcher); + } + + if (SUCCEEDED(result)) + { + // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel + // to perform the runtime-scale behavior. This swapchain is cached here because there are + // no methods for retreiving the currently configured on from ISwapChainPanelNative. + mSwapChain = newSwapChain; + result = newSwapChain.CopyTo(swapChain); + } + + // If the host is responsible for scaling the output of the swapchain, then + // scale it now before returning an instance to the caller. This is done by + // first reading the current size of the swapchain panel, then scaling + if (SUCCEEDED(result)) + { + if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) + { + result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, + ¤tPanelSize); + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result)) + { + result = scaleSwapChain(currentPanelSize, mClientRect); + } + } + } + + return result; +} + +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect) +{ + Size renderScale = {windowSize.Width / (float)clientRect.right, + windowSize.Height / (float)clientRect.bottom}; + // Setup a scale matrix for the swap chain + DXGI_MATRIX_3X2_F scaleMatrix = {}; + scaleMatrix._11 = renderScale.Width; + scaleMatrix._22 = renderScale.Height; + + ComPtr<IDXGISwapChain2> swapChain2; + HRESULT result = mSwapChain.As(&swapChain2); + if (SUCCEEDED(result)) + { + result = swapChain2->SetMatrixTransform(&scaleMatrix); + } + + return result; +} + +HRESULT GetSwapChainPanelSize( + const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, + const ComPtr<ICoreDispatcher> &dispatcher, + Size *windowSize) +{ + ComPtr<IUIElement> uiElement; + HRESULT result = swapChainPanel.As(&uiElement); + if (SUCCEEDED(result)) + { + result = RunOnUIThread( + [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher); + } + + return result; +} +}
\ No newline at end of file diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h new file mode 100755 index 000000000..f9a2fc0e4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 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. +// + +// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + +#include <memory> + +namespace rx +{ +class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow> +{ + public: + ~SwapChainPanelNativeWindow(); + + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory2 *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + IDXGISwapChain1 **swapChain) override; + + protected: + HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; + + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + + private: + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel; + ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; + ComPtr<IDXGISwapChain1> mSwapChain; +}; + +[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] +class SwapChainPanelSizeChangedHandler : + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> +{ + public: + SwapChainPanelSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // ISizeChangedEventHandler + IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + // The size of the ISwapChainPanel control is returned in DIPs. + // We are keeping these in dips because the swapchain created for composition + // also uses dip units. This keeps dimensions, viewports, etc in the same unit. + // XAML Clients of the ISwapChainPanel are required to use dips to define their + // layout sizes as well. + ABI::Windows::Foundation::Size newSize; + HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); + if (SUCCEEDED(result)) + { + host->setNewClientSize(newSize); + } + } + + return S_OK; + } + + private: + std::weak_ptr<InspectableNativeWindow> mHost; +}; + +HRESULT GetSwapChainPanelSize( + const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, + const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher, + Size *windowSize); +} +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp new file mode 100755 index 000000000..026c42449 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp @@ -0,0 +1,460 @@ +// +// Copyright (c) 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. +// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP +// to ensure that the proper defines are set when including additional +// headers which rely on Windows Store specific configuration. +// This would normally be defined already but this unittest exe is compiled +// as a desktop application which results in WINAPI_FAMILY being +// set to WINAPI_FAMILY_DESKTOP_APP +#undef WINAPI_FAMILY +#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include <angle_windowsstore.h> +#include <windows.ui.xaml.h> +#include <windows.ui.xaml.media.dxinterop.h> + +using namespace rx; +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::System; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Data; +using namespace ABI::Windows::UI::Xaml::Media; +using namespace ABI::Windows::UI::Xaml::Input; +using namespace ABI::Windows::UI::Xaml; + +namespace +{ + +// Mock ISwapChainPanel +class MockSwapChainPanel : public ISwapChainPanel, + IFrameworkElement, + IUIElement, + ISwapChainPanelNative +{ + public: + // IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) + { + *ppvObject = NULL; + + if (IsEqualIID(IID_IUnknown, riid)) + { + *ppvObject = reinterpret_cast<IUnknown*>(this); + return S_OK; + } + + if (IsEqualIID(IID_IInspectable, riid)) + { + *ppvObject = reinterpret_cast<IInspectable*>(this); + return S_OK; + } + + if (IsEqualIID(IID_ISwapChainPanel, riid)) + { + *ppvObject = static_cast<ISwapChainPanel*>(this); + return S_OK; + } + + if (IsEqualIID(IID_IFrameworkElement, riid)) + { + *ppvObject = static_cast<IFrameworkElement*>(this); + return S_OK; + } + + if (IsEqualIID(IID_IUIElement, riid)) + { + *ppvObject = static_cast<IUIElement*>(this); + return S_OK; + } + + if (IsEqualIID(__uuidof(ISwapChainPanelNative), riid)) + { + *ppvObject = static_cast<ISwapChainPanelNative*>(this); + return S_OK; + } + + return E_NOINTERFACE; + } + + STDMETHOD_(ULONG, AddRef)(){ return 1; } + STDMETHOD_(ULONG, Release)(){ return 1; } + + // IInspectable + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *)); + + // ISwapChainPanelNative + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, SetSwapChain, HRESULT(IDXGISwapChain *)); + + // ISwapChainPanel + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleX, HRESULT(FLOAT *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleY, HRESULT(FLOAT *)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CompositionScaleChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CXaml__CControls__CSwapChainPanel_IInspectable*, EventRegistrationToken*)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CompositionScaleChanged, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CreateCoreIndependentInputSource, HRESULT(CoreInputDeviceTypes, ICoreInputSourceBase**)); + + // IFrameworkElement + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Triggers, HRESULT(__FIVector_1_Windows__CUI__CXaml__CTriggerBase **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Resources, HRESULT(IResourceDictionary **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Resources, HRESULT(IResourceDictionary *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Tag, HRESULT(IInspectable **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Tag, HRESULT(IInspectable *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Language, HRESULT(HSTRING *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Language, HRESULT(HSTRING)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualWidth, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualHeight, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Width, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Width, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Height, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Height, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinWidth, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinWidth, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxWidth, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxWidth, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinHeight, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinHeight, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxHeight, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxHeight, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_HorizontalAlignment, HRESULT(HorizontalAlignment *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_HorizontalAlignment, HRESULT(HorizontalAlignment)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_VerticalAlignment, HRESULT(VerticalAlignment *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_VerticalAlignment, HRESULT(VerticalAlignment)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Margin, HRESULT(Thickness *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Margin, HRESULT(Thickness)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Name, HRESULT(HSTRING*)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Name, HRESULT(HSTRING)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_BaseUri, HRESULT(IUriRuntimeClass **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DataContext, HRESULT(IInspectable **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_DataContext, HRESULT(IInspectable *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Style, HRESULT(IStyle **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Style, HRESULT(IStyle *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Parent, HRESULT(IDependencyObject **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(FlowDirection *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(FlowDirection)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Loaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Loaded, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Unloaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Unloaded, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(ISizeChangedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LayoutUpdated, HRESULT(__FIEventHandler_1_IInspectable *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LayoutUpdated, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, FindName, HRESULT(HSTRING, IInspectable **)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, SetBinding, HRESULT(IDependencyProperty *, IBindingBase *)); + + // IUIElement + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DesiredSize, HRESULT(ABI::Windows::Foundation::Size *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AllowDrop, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_AllowDrop, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Opacity, HRESULT(DOUBLE *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Opacity, HRESULT(DOUBLE)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Clip, HRESULT(IRectangleGeometry **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Clip, HRESULT(IRectangleGeometry *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransform, HRESULT(ITransform **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransform, HRESULT(ITransform *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Projection, HRESULT(IProjection **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Projection, HRESULT(IProjection *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransformOrigin, HRESULT(Point *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransformOrigin, HRESULT(Point)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHitTestVisible, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHitTestVisible, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visibility, HRESULT(Visibility *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Visibility, HRESULT(Visibility)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderSize, HRESULT(Size *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_UseLayoutRounding, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_UseLayoutRounding, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CacheMode, HRESULT(ICacheMode **)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_CacheMode, HRESULT(ICacheMode *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsTapEnabled, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsTapEnabled, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsDoubleTapEnabled, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsDoubleTapEnabled, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsRightTapEnabled, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsRightTapEnabled, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHoldingEnabled, HRESULT(boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHoldingEnabled, HRESULT(boolean)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ManipulationMode, HRESULT(ManipulationModes *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_ManipulationMode, HRESULT(ManipulationModes)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCaptures, HRESULT(__FIVectorView_1_Windows__CUI__CXaml__CInput__CPointer **)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(IKeyEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(IKeyEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_GotFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_GotFocus, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LostFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LostFocus, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragEnter, HRESULT(IDragEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragEnter, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragLeave, HRESULT(IDragEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragLeave, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragOver, HRESULT(IDragEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragOver, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Drop, HRESULT(IDragEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Drop, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCanceled, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCanceled, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(IPointerEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Tapped, HRESULT(ITappedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Tapped, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DoubleTapped, HRESULT(IDoubleTappedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DoubleTapped, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Holding, HRESULT(IHoldingEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Holding, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_RightTapped, HRESULT(IRightTappedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_RightTapped, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarting, HRESULT(IManipulationStartingEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarting, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationInertiaStarting, HRESULT(IManipulationInertiaStartingEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationInertiaStarting, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarted, HRESULT(IManipulationStartedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarted, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationDelta, HRESULT(IManipulationDeltaEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationDelta, HRESULT(EventRegistrationToken)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationCompleted, HRESULT(IManipulationCompletedEventHandler *, EventRegistrationToken *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationCompleted, HRESULT(EventRegistrationToken)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Measure, HRESULT(Size)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Arrange, HRESULT(Rect)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CapturePointer, HRESULT(IPointer *, boolean *)); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT(IPointer *)); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCaptures, HRESULT()); + MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE, AddHandler, HRESULT(IRoutedEvent *, IInspectable *, boolean)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, RemoveHandler, HRESULT(IRoutedEvent *, IInspectable *)); + MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, TransformToVisual, HRESULT(IUIElement *, IGeneralTransform **)); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateMeasure, HRESULT()); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateArrange, HRESULT()); + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, UpdateLayout, HRESULT()); +}; + +HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap) +{ + HRESULT result = S_OK; + ComPtr<IPropertySet> propertySet; + ComPtr<IActivationFactory> propertySetFactory; + result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertySetFactory->ActivateInstance(&propertySet); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertySet.CopyTo(propertyMap); + EXPECT_HRESULT_SUCCEEDED(result); + + return result; +} + +HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics) +{ + ComPtr<IPropertyValueStatics> propertyValueStatics; + HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics); + EXPECT_HRESULT_SUCCEEDED(result); + + result = propertyValueStatics.CopyTo(propertyStatics); + EXPECT_HRESULT_SUCCEEDED(result); + + return result; +} + +HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable) +{ + boolean propertyReplaced = false; + return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced); +} + +void expectNativeWindowInitCalls(MockSwapChainPanel &panel, bool expectRenderSize) +{ + if (expectRenderSize) + { + EXPECT_CALL(panel, get_RenderSize(testing::_)).Times(1); + } + + EXPECT_CALL(panel, add_SizeChanged(testing::_, testing::_)).Times(1); + EXPECT_CALL(panel, remove_SizeChanged(testing::_)).Times(1); +} + +TEST(NativeWindowTest, SwapChainPanelByItself) +{ + MockSwapChainPanel mockSwapChainPanel; + NativeWindow nativeWindow(reinterpret_cast<IInspectable*>(&mockSwapChainPanel)); + expectNativeWindowInitCalls(mockSwapChainPanel, true); + EXPECT_TRUE(nativeWindow.initialize()); +} + +TEST(NativeWindowTest, SwapChainPanelInPropertySet) +{ + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockSwapChainPanel mockSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + + // Create a simple property set with the swapchainpanel + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel))); + + // Check native window init calls + NativeWindow nativeWindow(propertySet.Get()); + expectNativeWindowInitCalls(mockSwapChainPanel, true); + EXPECT_TRUE(nativeWindow.initialize()); + } + CoUninitialize(); +} + +TEST(NativeWindowTest, SwapChainPanelInPropertySetWithSizeAndScale) +{ + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockSwapChainPanel mockSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + ComPtr<IPropertyValueStatics> propertyValueStatics; + ComPtr<IPropertyValue> singleValue; + ComPtr<IPropertyValue> sizeValue; + + // Create a simple property set with the swapchainpanel + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel))); + + // Add a valid scale factor to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSingle(0.5f, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get()))); + + // Add a valid size to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSize({ 480, 800 }, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get()))); + + // Check native window init fails, since we shouldn't be able to set a size and a scale together + NativeWindow nativeWindow(propertySet.Get()); + EXPECT_FALSE(nativeWindow.initialize()); + } + CoUninitialize(); +} + +// Tests that the scale property works as expected in a property set with a SwapChainPanel +class SwapChainPanelScaleTest : public testing::TestWithParam<std::pair<float, bool>> +{ +}; + +TEST_P(SwapChainPanelScaleTest, ValidateScale) +{ + float scale = GetParam().first; + bool expectedResult = GetParam().second; + + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockSwapChainPanel mockSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + ComPtr<IPropertyValueStatics> propertyValueStatics; + ComPtr<IPropertyValue> singleValue; + + // Create a simple property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel))); + + // Add a valid scale factor to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get()))); + + // Check native window init status and calls to the mock swapchainpanel + NativeWindow nativeWindow(propertySet.Get()); + if (expectedResult) + { + expectNativeWindowInitCalls(mockSwapChainPanel, true); + } + + EXPECT_EQ(nativeWindow.initialize(), expectedResult); + } + CoUninitialize(); +} + +typedef std::pair<float, bool> scaleValidPair; +static const scaleValidPair scales[] = { scaleValidPair(1.0f, true), + scaleValidPair(0.5f, true), + scaleValidPair(0.0f, false), + scaleValidPair(0.01f, true), + scaleValidPair(2.00f, true) }; + +INSTANTIATE_TEST_CASE_P(NativeWindowTest, + SwapChainPanelScaleTest, + testing::ValuesIn(scales)); + +// Tests that the size property works as expected in a property set with a SwapChainPanel +class SwapChainPanelSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>> +{ +}; + +TEST_P(SwapChainPanelSizeTest, ValidateSize) +{ + Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) }; + bool expectedResult = std::get<2>(GetParam()); + + // COM is required to be initialized for creation of the property set + EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)); + { + MockSwapChainPanel mockSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> propertySet; + ComPtr<IPropertyValueStatics> propertyValueStatics; + ComPtr<IPropertyValue> sizeValue; + + // Create a simple property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet)); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel))); + + // Add a valid size to the property set + EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf())); + propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf())); + EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get()))); + + // Check native window init status and calls to the mock swapchainpanel + NativeWindow nativeWindow(propertySet.Get()); + if (expectedResult) + { + expectNativeWindowInitCalls(mockSwapChainPanel, false); + } + + EXPECT_EQ(nativeWindow.initialize(), expectedResult); + } + CoUninitialize(); +} + +typedef std::tuple<float, float, bool> sizeValidPair; +static const sizeValidPair sizes[] = { sizeValidPair( 800, 480, true), + sizeValidPair( 0, 480, false), + sizeValidPair( 800, 0, false), + sizeValidPair( 0, 0, false) }; + +INSTANTIATE_TEST_CASE_P(NativeWindowTest, + SwapChainPanelSizeTest, + testing::ValuesIn(sizes)); + +} // namespace diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp new file mode 100755 index 000000000..95320f228 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -0,0 +1,694 @@ +// +// Copyright (c) 2002-2010 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. +// + +// Blit9.cpp: Surface copy utility class. + +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" + +namespace +{ +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" + +const BYTE* const g_shaderCode[] = +{ + g_vs20_standardvs, + g_vs20_flipyvs, + g_ps20_passthroughps, + g_ps20_luminanceps, + g_ps20_componentmaskps +}; + +const size_t g_shaderSize[] = +{ + sizeof(g_vs20_standardvs), + sizeof(g_vs20_flipyvs), + sizeof(g_ps20_passthroughps), + sizeof(g_ps20_luminanceps), + sizeof(g_ps20_componentmaskps) +}; +} + +namespace rx +{ + +Blit9::Blit9(Renderer9 *renderer) + : mRenderer(renderer), + mGeometryLoaded(false), + mQuadVertexBuffer(NULL), + mQuadVertexDeclaration(NULL), + mSavedStateBlock(NULL), + mSavedRenderTarget(NULL), + mSavedDepthStencil(NULL) +{ + memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); +} + +Blit9::~Blit9() +{ + SafeRelease(mSavedStateBlock); + SafeRelease(mQuadVertexBuffer); + SafeRelease(mQuadVertexDeclaration); + + for (int i = 0; i < SHADER_COUNT; i++) + { + SafeRelease(mCompiledShaders[i]); + } +} + +gl::Error Blit9::initialize() +{ + if (mGeometryLoaded) + { + return gl::Error(GL_NO_ERROR); + } + + static const float quad[] = + { + -1, -1, + -1, 1, + 1, -1, + 1, 1 + }; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result); + } + + void *lockPtr = NULL; + result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); + + if (FAILED(result) || lockPtr == NULL) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result); + } + + memcpy(lockPtr, quad, sizeof(quad)); + mQuadVertexBuffer->Unlock(); + + static const D3DVERTEXELEMENT9 elements[] = + { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + D3DDECL_END() + }; + + result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result); + } + + mGeometryLoaded = true; + return gl::Error(GL_NO_ERROR); +} + +template <class D3DShaderType> +gl::Error Blit9::setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DShaderType *shader = nullptr; + + if (mCompiledShaders[source] != NULL) + { + shader = static_cast<D3DShaderType*>(mCompiledShaders[source]); + } + else + { + const BYTE* shaderCode = g_shaderCode[source]; + size_t shaderSize = g_shaderSize[source]; + ANGLE_TRY((mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader)); + mCompiledShaders[source] = shader; + } + + HRESULT hr = (device->*setShader)(shader); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::setVertexShader(ShaderId shader) +{ + return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); +} + +gl::Error Blit9::setPixelShader(ShaderId shader) +{ + return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); +} + +RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = desc.Width; + rect.bottom = desc.Height; + + return rect; +} + +gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + ANGLE_TRY(initialize()); + + IDirect3DTexture9 *texture = NULL; + ANGLE_TRY(copySurfaceToTexture(source, getSurfaceRect(source), &texture)); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setVertexShader(SHADER_VS_STANDARD); + setPixelShader(SHADER_PS_PASSTHROUGH); + + setCommonBlitState(); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + setViewport(getSurfaceRect(dest), gl::Offset(0, 0, 0)); + + render(); + + SafeRelease(texture); + + restoreState(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + ANGLE_TRY(initialize()); + + const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget9 = nullptr; + ANGLE_TRY(colorbuffer->getRenderTarget(&renderTarget9)); + ASSERT(renderTarget9); + + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + + IDirect3DSurface9 *destSurface = NULL; + TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); + gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface); + if (error.isError()) + { + SafeRelease(source); + return error; + } + ASSERT(destSurface); + + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + + SafeRelease(destSurface); + SafeRelease(source); + + return result; +} + +gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget9 = nullptr; + error = colorbuffer->getRenderTarget(&renderTarget9); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget9); + + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + + IDirect3DSurface9 *destSurface = NULL; + TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); + error = storage9->getSurfaceLevel(target, level, true, &destSurface); + if (error.isError()) + { + SafeRelease(source); + return error; + } + ASSERT(destSurface); + + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + + SafeRelease(destSurface); + SafeRelease(source); + + return result; +} + +gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) +{ + ASSERT(source != NULL && dest != NULL); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + D3DSURFACE_DESC destDesc; + source->GetDesc(&sourceDesc); + dest->GetDesc(&destDesc); + + if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && + d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect + { + RECT destRect = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (sourceRect.bottom - sourceRect.top)}; + HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); + } + else + { + return formatConvert(source, sourceRect, destFormat, destOffset, dest); + } +} + +gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *texture = NULL; + error = copySurfaceToTexture(source, sourceRect, &texture); + if (error.isError()) + { + return error; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setViewport(sourceRect, destOffset); + + setCommonBlitState(); + + error = setFormatConvertShaders(destFormat); + if (!error.isError()) + { + render(); + } + + SafeRelease(texture); + + restoreState(); + + return error; +} + +gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) +{ + gl::Error error = setVertexShader(SHADER_VS_STANDARD); + if (error.isError()) + { + return error; + } + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_RG_EXT: + case GL_RED_EXT: + case GL_ALPHA: + error = setPixelShader(SHADER_PS_COMPONENTMASK); + break; + + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + error = setPixelShader(SHADER_PS_LUMINANCE); + break; + } + + if (error.isError()) + { + return error; + } + + enum { X = 0, Y = 1, Z = 2, W = 3 }; + + // The meaning of this constant depends on the shader that was selected. + // See the shader assembly code above for details. + // Allocate one array for both registers and split it into two float4's. + float psConst[8] = { 0 }; + float *multConst = &psConst[0]; + float *addConst = &psConst[4]; + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_RGB: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RG_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RED_EXT: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_ALPHA: + multConst[X] = 0; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_LUMINANCE: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_LUMINANCE_ALPHA: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + } + + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture) +{ + ASSERT(surface); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + surface->GetDesc(&sourceDesc); + + const auto destWidth = sourceRect.right - sourceRect.left; + const auto destHeight = sourceRect.bottom - sourceRect.top; + + // Copy the render target into a texture + IDirect3DTexture9 *texture; + HRESULT result = device->CreateTexture(destWidth, destHeight, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result); + } + + IDirect3DSurface9 *textureSurface; + result = texture->GetSurfaceLevel(0, &textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result); + } + + mRenderer->endScene(); + + if (sourceRect.left < sourceDesc.Width && sourceRect.right > 0 && + sourceRect.top < sourceDesc.Height && sourceRect.bottom > 0) + { + RECT validSourceRect = sourceRect; + RECT validDestRect = {0, 0, destWidth, destHeight}; + + if (sourceRect.left < 0) { + validSourceRect.left += 0 - sourceRect.left; + validDestRect.left += 0 - sourceRect.left; + } + + if (sourceRect.right > sourceDesc.Width) { + validSourceRect.right -= sourceRect.right - sourceDesc.Width; + validDestRect.right -= sourceRect.right - sourceDesc.Width; + } + + if (sourceRect.top < 0) { + validSourceRect.top += 0 - sourceRect.top; + validDestRect.top += 0 - sourceRect.top; + } + + if (sourceRect.bottom > sourceDesc.Height) { + validSourceRect.bottom -= sourceRect.bottom - sourceDesc.Height; + validDestRect.bottom -= sourceRect.bottom - sourceDesc.Height; + } + + ASSERT(validSourceRect.left < validSourceRect.right); + ASSERT(validSourceRect.top < validSourceRect.bottom); + ASSERT(validDestRect.left < validDestRect.right); + ASSERT(validDestRect.top < validDestRect.bottom); + result = device->StretchRect(surface, &validSourceRect, textureSurface, + &validDestRect, D3DTEXF_NONE); + } + SafeRelease(textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result); + } + + *outTexture = texture; + return gl::Error(GL_NO_ERROR); +} + +void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DVIEWPORT9 vp; + vp.X = offset.x; + vp.Y = offset.y; + vp.Width = sourceRect.right - sourceRect.left; + vp.Height = sourceRect.bottom - sourceRect.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + device->SetViewport(&vp); + + float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; + device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); +} + +void Blit9::setCommonBlitState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(NULL); + + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle + device->SetScissorRect(&scissorRect); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } +} + +void Blit9::render() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); + hr = device->SetVertexDeclaration(mQuadVertexDeclaration); + + mRenderer->startScene(); + hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); +} + +void Blit9::saveState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr; + + device->GetDepthStencilSurface(&mSavedDepthStencil); + device->GetRenderTarget(0, &mSavedRenderTarget); + + if (mSavedStateBlock == NULL) + { + hr = device->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + setCommonBlitState(); + + static const float dummyConst[8] = { 0 }; + + device->SetVertexShader(NULL); + device->SetVertexShaderConstantF(0, dummyConst, 2); + device->SetPixelShader(NULL); + device->SetPixelShaderConstantF(0, dummyConst, 2); + + D3DVIEWPORT9 dummyVp; + dummyVp.X = 0; + dummyVp.Y = 0; + dummyVp.Width = 1; + dummyVp.Height = 1; + dummyVp.MinZ = 0; + dummyVp.MaxZ = 1; + + device->SetViewport(&dummyVp); + + device->SetTexture(0, NULL); + + device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); + + device->SetVertexDeclaration(mQuadVertexDeclaration); + + hr = device->EndStateBlock(&mSavedStateBlock); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + hr = mSavedStateBlock->Capture(); + ASSERT(SUCCEEDED(hr)); + } +} + +void Blit9::restoreState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(mSavedDepthStencil); + SafeRelease(mSavedDepthStencil); + + device->SetRenderTarget(0, mSavedRenderTarget); + SafeRelease(mSavedRenderTarget); + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + mSavedStateBlock->Apply(); + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h new file mode 100755 index 000000000..586abd258 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h @@ -0,0 +1,97 @@ +// +// Copyright (c) 2002-2010 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. +// + +// Blit9.cpp: Surface copy utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#include <GLES2/gl2.h> + +namespace gl +{ +class Framebuffer; +struct Offset; +} + +namespace rx +{ +class Renderer9; +class TextureStorage; + +class Blit9 : angle::NonCopyable +{ + public: + explicit Blit9(Renderer9 *renderer); + ~Blit9(); + + gl::Error initialize(); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. + gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); + + // 2x2 box filter sample from source to dest. + // Requires that source is RGB(A) and dest has the same format as source. + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + private: + Renderer9 *mRenderer; + + bool mGeometryLoaded; + IDirect3DVertexBuffer9 *mQuadVertexBuffer; + IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; + + gl::Error setFormatConvertShaders(GLenum destFormat); + + gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); + gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture); + void setViewport(const RECT &sourceRect, const gl::Offset &offset); + void setCommonBlitState(); + RECT getSurfaceRect(IDirect3DSurface9 *surface) const; + + // This enum is used to index mCompiledShaders and mShaderSource. + enum ShaderId + { + SHADER_VS_STANDARD, + SHADER_VS_FLIPY, + SHADER_PS_PASSTHROUGH, + SHADER_PS_LUMINANCE, + SHADER_PS_COMPONENTMASK, + SHADER_COUNT + }; + + // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. + IUnknown *mCompiledShaders[SHADER_COUNT]; + + template <class D3DShaderType> + gl::Error setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); + + gl::Error setVertexShader(ShaderId shader); + gl::Error setPixelShader(ShaderId shader); + void render(); + + void saveState(); + void restoreState(); + IDirect3DStateBlock9 *mSavedStateBlock; + IDirect3DSurface9 *mSavedRenderTarget; + IDirect3DSurface9 *mSavedDepthStencil; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp new file mode 100755 index 000000000..b8abf3845 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -0,0 +1,112 @@ +// +// Copyright 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. +// + +// Buffer9.cpp Defines the Buffer9 class. + +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Buffer9::Buffer9(const gl::BufferState &state, Renderer9 *renderer) + : BufferD3D(state, renderer), mSize(0) +{} + +Buffer9::~Buffer9() +{ + mSize = 0; +} + +gl::Error Buffer9::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage) +{ + if (size > mMemory.size()) + { + if (!mMemory.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); + } + } + + mSize = size; + if (data && size > 0) + { + memcpy(mMemory.data(), data, size); + } + + updateD3DBufferUsage(usage); + + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::getData(const uint8_t **outData) +{ + *outData = mMemory.data(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset) +{ + if (offset + size > mMemory.size()) + { + if (!mMemory.resize(offset + size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); + } + } + + mSize = std::max(mSize, offset + size); + if (data && size > 0) + { + memcpy(mMemory.data() + offset, data, size); + } + + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + // Note: this method is currently unreachable + Buffer9* sourceBuffer = GetAs<Buffer9>(source); + ASSERT(sourceBuffer); + + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); + + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +// We do not support buffer mapping in D3D9 +gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Buffer9::unmap(GLboolean *result) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Buffer9::markTransformFeedbackUsage() +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h new file mode 100755 index 000000000..dd7671827 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -0,0 +1,50 @@ +// +// Copyright 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. +// + +// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ + +#include "common/MemoryBuffer.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" + +namespace rx +{ +class Renderer9; + +class Buffer9 : public BufferD3D +{ + public: + Buffer9(const gl::BufferState &state, Renderer9 *renderer); + virtual ~Buffer9(); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual bool supportsDirectBinding() const { return false; } + gl::Error getData(const uint8_t **outData) override; + + // BufferImpl implementation + gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override; + gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override; + gl::Error copySubData(BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) override; + gl::Error map(GLenum access, GLvoid **mapPtr) override; + gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override; + gl::Error unmap(GLboolean *result) override; + gl::Error markTransformFeedbackUsage() override; + + private: + MemoryBuffer mMemory; + size_t mSize; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp new file mode 100755 index 000000000..c38bc1b11 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp @@ -0,0 +1,258 @@ +// +// Copyright 2016 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. +// +// Context9: +// D3D9-specific functionality associated with a GL Context. +// + +#include "libANGLE/renderer/d3d/d3d9/Context9.h" + +#include "common/string_utils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h" + +namespace rx +{ + +Context9::Context9(const gl::ContextState &state, Renderer9 *renderer) + : ContextImpl(state), mRenderer(renderer) +{ +} + +Context9::~Context9() +{ +} + +gl::Error Context9::initialize() +{ + return gl::NoError(); +} + +CompilerImpl *Context9::createCompiler() +{ + return new CompilerD3D(SH_HLSL_3_0_OUTPUT); +} + +ShaderImpl *Context9::createShader(const gl::ShaderState &data) +{ + return new ShaderD3D(data, mRenderer->getWorkarounds()); +} + +ProgramImpl *Context9::createProgram(const gl::ProgramState &data) +{ + return new ProgramD3D(data, mRenderer); +} + +FramebufferImpl *Context9::createFramebuffer(const gl::FramebufferState &data) +{ + return new Framebuffer9(data, mRenderer); +} + +TextureImpl *Context9::createTexture(const gl::TextureState &state) +{ + switch (state.getTarget()) + { + case GL_TEXTURE_2D: + return new TextureD3D_2D(state, mRenderer); + case GL_TEXTURE_CUBE_MAP: + return new TextureD3D_Cube(state, mRenderer); + case GL_TEXTURE_EXTERNAL_OES: + return new TextureD3D_External(state, mRenderer); + default: + UNREACHABLE(); + } + return nullptr; +} + +RenderbufferImpl *Context9::createRenderbuffer() +{ + return new RenderbufferD3D(mRenderer); +} + +BufferImpl *Context9::createBuffer(const gl::BufferState &state) +{ + return new Buffer9(state, mRenderer); +} + +VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data) +{ + return new VertexArray9(data); +} + +QueryImpl *Context9::createQuery(GLenum type) +{ + return new Query9(mRenderer, type); +} + +FenceNVImpl *Context9::createFenceNV() +{ + return new FenceNV9(mRenderer); +} + +FenceSyncImpl *Context9::createFenceSync() +{ + // D3D9 doesn't support ES 3.0 and its sync objects. + UNREACHABLE(); + return nullptr; +} + +TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state) +{ + UNREACHABLE(); + return nullptr; +} + +SamplerImpl *Context9::createSampler() +{ + return new SamplerD3D(); +} + +std::vector<PathImpl *> Context9::createPaths(GLsizei) +{ + return std::vector<PathImpl *>(); +} + +gl::Error Context9::flush() +{ + return mRenderer->flush(); +} + +gl::Error Context9::finish() +{ + return mRenderer->finish(); +} + +gl::Error Context9::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + return mRenderer->genericDrawArrays(this, mode, first, count, 1); +} + +gl::Error Context9::drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount); +} + +gl::Error Context9::drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange); +} + +gl::Error Context9::drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange); +} + +gl::Error Context9::drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange); +} + +GLenum Context9::getResetStatus() +{ + return mRenderer->getResetStatus(); +} + +std::string Context9::getVendorString() const +{ + return mRenderer->getVendorString(); +} + +std::string Context9::getRendererDescription() const +{ + return mRenderer->getRendererDescription(); +} + +void Context9::insertEventMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast<size_t>(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->setMarker(optionalString.value().data()); + } +} + +void Context9::pushGroupMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast<size_t>(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->beginEvent(optionalString.value().data()); + } +} + +void Context9::popGroupMarker() +{ + mRenderer->getAnnotator()->endEvent(); +} + +void Context9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(state, dirtyBits); +} + +GLint Context9::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 Context9::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void Context9::onMakeCurrent(const gl::ContextState &data) +{ +} + +const gl::Caps &Context9::getNativeCaps() const +{ + return mRenderer->getNativeCaps(); +} + +const gl::TextureCapsMap &Context9::getNativeTextureCaps() const +{ + return mRenderer->getNativeTextureCaps(); +} + +const gl::Extensions &Context9::getNativeExtensions() const +{ + return mRenderer->getNativeExtensions(); +} + +const gl::Limitations &Context9::getNativeLimitations() const +{ + return mRenderer->getNativeLimitations(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h new file mode 100755 index 000000000..aeb18ff5e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h @@ -0,0 +1,126 @@ +// +// Copyright 2016 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. +// +// Context9: +// D3D9-specific functionality associated with a GL Context. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_ + +#include "libANGLE/renderer/ContextImpl.h" + +namespace rx +{ +class Renderer9; + +class Context9 : public ContextImpl +{ + public: + Context9(const gl::ContextState &state, Renderer9 *renderer); + ~Context9() override; + + gl::Error initialize() override; + + // Shader creation + CompilerImpl *createCompiler() override; + ShaderImpl *createShader(const gl::ShaderState &data) override; + ProgramImpl *createProgram(const gl::ProgramState &data) override; + + // Framebuffer creation + FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override; + + // Texture creation + TextureImpl *createTexture(const gl::TextureState &state) override; + + // Renderbuffer creation + RenderbufferImpl *createRenderbuffer() override; + + // Buffer creation + BufferImpl *createBuffer(const gl::BufferState &state) override; + + // Vertex Array creation + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + + // Query and Fence creation + QueryImpl *createQuery(GLenum type) override; + FenceNVImpl *createFenceNV() override; + FenceSyncImpl *createFenceSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler() override; + + // Path object creation + std::vector<PathImpl *> createPaths(GLsizei) override; + + // Flush and finish. + gl::Error flush() override; + gl::Error finish() override; + + // Drawing methods. + gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override; + gl::Error drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + gl::Error drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) override; + gl::Error drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // Debug markers. + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // State sync with dirty bits. + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::ContextState &data) override; + + // Caps queries + const gl::Caps &getNativeCaps() const override; + const gl::TextureCapsMap &getNativeTextureCaps() const override; + const gl::Extensions &getNativeExtensions() const override; + const gl::Limitations &getNativeLimitations() const override; + + private: + Renderer9 *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp new file mode 100755 index 000000000..6ec35e16a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp @@ -0,0 +1,36 @@ +// +// Copyright 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. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" + +#include "common/platform.h" + +namespace rx +{ + +void DebugAnnotator9::beginEvent(const wchar_t *eventName) +{ + D3DPERF_BeginEvent(0, eventName); +} + +void DebugAnnotator9::endEvent() +{ + D3DPERF_EndEvent(); +} + +void DebugAnnotator9::setMarker(const wchar_t *markerName) +{ + D3DPERF_SetMarker(0, markerName); +} + +bool DebugAnnotator9::getStatus() +{ + return !!D3DPERF_GetStatus(); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h new file mode 100755 index 000000000..54e3bb949 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h @@ -0,0 +1,29 @@ +// +// Copyright 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. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ + +#include "common/debug.h" + +namespace rx +{ + +class DebugAnnotator9 : public gl::DebugAnnotator +{ + public: + DebugAnnotator9() {} + void beginEvent(const wchar_t *eventName) override; + void endEvent() override; + void setMarker(const wchar_t *markerName) override; + bool getStatus() override; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp new file mode 100755 index 000000000..330068127 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp @@ -0,0 +1,94 @@ +// +// Copyright (c) 2013 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. +// + +// Fence9.cpp: Defines the rx::FenceNV9 class. + +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +FenceNV9::FenceNV9(Renderer9 *renderer) + : FenceNVImpl(), + mRenderer(renderer), + mQuery(NULL) +{ +} + +FenceNV9::~FenceNV9() +{ + SafeRelease(mQuery); +} + +gl::Error FenceNV9::set(GLenum condition) +{ + if (!mQuery) + { + gl::Error error = mRenderer->allocateEventQuery(&mQuery); + if (error.isError()) + { + return error; + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuery); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNV9::test(GLboolean *outFinished) +{ + return testHelper(true, outFinished); +} + +gl::Error FenceNV9::finish() +{ + GLboolean finished = GL_FALSE; + while (finished != GL_TRUE) + { + gl::Error error = testHelper(true, &finished); + if (error.isError()) + { + return error; + } + + Sleep(0); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished) +{ + ASSERT(mQuery); + + DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); + HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + } + else if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); + } + + ASSERT(result == S_OK || result == S_FALSE); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h new file mode 100755 index 000000000..200ac68d2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2013 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. +// + +// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" + +namespace rx +{ +class Renderer9; + +class FenceNV9 : public FenceNVImpl +{ + public: + explicit FenceNV9(Renderer9 *renderer); + ~FenceNV9() override; + + gl::Error set(GLenum condition) override; + gl::Error test(GLboolean *outFinished) override; + gl::Error finish() override; + + private: + gl::Error testHelper(bool flushCommandBuffer, GLboolean *outFinished); + + Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp new file mode 100755 index 000000000..18e1b3da4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -0,0 +1,410 @@ +// +// Copyright 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. +// + +// Framebuffer9.cpp: Implements the Framebuffer9 class. + +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" + +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ContextImpl.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" + +namespace rx +{ + +Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer) + : FramebufferD3D(data, renderer), mRenderer(renderer) +{ + ASSERT(mRenderer != nullptr); +} + +Framebuffer9::~Framebuffer9() +{ +} + +gl::Error Framebuffer9::discard(size_t, const GLenum *) +{ + // Extension not implemented in D3D9 renderer + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::invalidate(size_t, const GLenum *) +{ + // Shouldn't ever reach here in D3D9 + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // Shouldn't ever reach here in D3D9 + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::clearImpl(ContextImpl *context, const ClearParameters &clearParams) +{ + const gl::FramebufferAttachment *colorAttachment = mState.getColorAttachment(0); + const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment(); + + gl::Error error = + mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment); + if (error.isError()) + { + return error; + } + + const gl::State &glState = context->getGLState(); + float nearZ = glState.getNearPlane(); + float farZ = glState.getFarPlane(); + mRenderer->setViewport(glState.getViewport(), nearZ, farZ, GL_TRIANGLES, + glState.getRasterizerState().frontFace, true); + + mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); + + return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); +} + +gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const +{ + ASSERT(pack.pixelBuffer.get() == nullptr); + + const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0); + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget = nullptr; + gl::Error error = colorbuffer->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + HRESULT result; + IDirect3DSurface9 *systemSurface = nullptr; + bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() && + area.x == 0 && area.y == 0 && + static_cast<UINT>(area.width) == desc.Width && static_cast<UINT>(area.height) == desc.Height && + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; + if (directToPixels) + { + // Use the pixels ptr as a shared handle to write directly into client's memory + result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels)); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, nullptr); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); + } + } + + result = device->GetRenderTargetData(surface, systemSurface); + SafeRelease(surface); + + if (FAILED(result)) + { + SafeRelease(systemSurface); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else + { + UNREACHABLE(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); + } + + if (directToPixels) + { + SafeRelease(systemSurface); + return gl::Error(GL_NO_ERROR); + } + + RECT rect; + rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width)); + rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height)); + rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width)); + rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + SafeRelease(systemSurface); + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); + } + + uint8_t *source = reinterpret_cast<uint8_t *>(lock.pBits); + int inputPitch = lock.Pitch; + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + gl::FormatType formatType(format, type); + + // TODO(jmadill): Maybe we can avoid a copy of pack parameters here? + PackPixelsParams packParams; + packParams.area.x = rect.left; + packParams.area.y = rect.top; + packParams.area.width = rect.right - rect.left; + packParams.area.height = rect.bottom - rect.top; + packParams.format = format; + packParams.type = type; + packParams.outputPitch = static_cast<GLuint>(outputPitch); + packParams.pack = pack; + + PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels); + + systemSurface->UnlockRect(); + SafeRelease(systemSurface); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::blitImpl(const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + ASSERT(filter == GL_NEAREST); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + mRenderer->endScene(); + + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0); + ASSERT(readBuffer); + + RenderTarget9 *readRenderTarget = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0); + ASSERT(drawBuffer); + + RenderTarget9 *drawRenderTarget = nullptr; + error = drawBuffer->getRenderTarget(&drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); + ASSERT(readSurface); + + IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); + ASSERT(drawSurface); + + gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + RECT srcRect; + srcRect.left = sourceArea.x; + srcRect.right = sourceArea.x + sourceArea.width; + srcRect.top = sourceArea.y; + srcRect.bottom = sourceArea.y + sourceArea.height; + + RECT dstRect; + dstRect.left = destArea.x; + dstRect.right = destArea.x + destArea.width; + dstRect.top = destArea.y; + dstRect.bottom = destArea.y + destArea.height; + + // Clip the rectangles to the scissor rectangle + if (scissor) + { + if (dstRect.left < scissor->x) + { + srcRect.left += (scissor->x - dstRect.left); + dstRect.left = scissor->x; + } + if (dstRect.top < scissor->y) + { + srcRect.top += (scissor->y - dstRect.top); + dstRect.top = scissor->y; + } + if (dstRect.right > scissor->x + scissor->width) + { + srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); + dstRect.right = scissor->x + scissor->width; + } + if (dstRect.bottom > scissor->y + scissor->height) + { + srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); + dstRect.bottom = scissor->y + scissor->height; + } + } + + // Clip the rectangles to the destination size + if (dstRect.left < 0) + { + srcRect.left += -dstRect.left; + dstRect.left = 0; + } + if (dstRect.right > dstSize.width) + { + srcRect.right -= (dstRect.right - dstSize.width); + dstRect.right = dstSize.width; + } + if (dstRect.top < 0) + { + srcRect.top += -dstRect.top; + dstRect.top = 0; + } + if (dstRect.bottom > dstSize.height) + { + srcRect.bottom -= (dstRect.bottom - dstSize.height); + dstRect.bottom = dstSize.height; + } + + // Clip the rectangles to the source size + if (srcRect.left < 0) + { + dstRect.left += -srcRect.left; + srcRect.left = 0; + } + if (srcRect.right > srcSize.width) + { + dstRect.right -= (srcRect.right - srcSize.width); + srcRect.right = srcSize.width; + } + if (srcRect.top < 0) + { + dstRect.top += -srcRect.top; + srcRect.top = 0; + } + if (srcRect.bottom > srcSize.height) + { + dstRect.bottom -= (srcRect.bottom - srcSize.height); + srcRect.bottom = srcSize.height; + } + + HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + if (blitDepth || blitStencil) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTarget9 *readDepthStencil = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(readDepthStencil); + + const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTarget9 *drawDepthStencil = nullptr; + error = drawBuffer->getRenderTarget(&drawDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(drawDepthStencil); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); + ASSERT(readDepthStencil); + + IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); + ASSERT(drawDepthStencil); + + HRESULT result = device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat()); + return d3dFormatInfo.info().glInternalFormat; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h new file mode 100755 index 000000000..8401350b3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -0,0 +1,54 @@ +// +// Copyright 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. +// + +// Framebuffer9.h: Defines the Framebuffer9 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ +class Renderer9; + +class Framebuffer9 : public FramebufferD3D +{ + public: + Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer); + virtual ~Framebuffer9(); + + gl::Error discard(size_t count, const GLenum *attachments) override; + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + + private: + gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override; + + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; + + gl::Error blitImpl(const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + Renderer9 *const mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp new file mode 100755 index 000000000..ad2c41584 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -0,0 +1,822 @@ +// +// Copyright (c) 2002-2012 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. +// + +// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#include "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Renderbuffer.h" +#include "common/utilities.h" + +namespace rx +{ + +Image9::Image9(Renderer9 *renderer) +{ + mSurface = NULL; + mRenderer = NULL; + + mD3DPool = D3DPOOL_SYSTEMMEM; + mD3DFormat = D3DFMT_UNKNOWN; + + mRenderer = renderer; +} + +Image9::~Image9() +{ + SafeRelease(mSurface); +} + +gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +{ + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result); + } + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result); + } + + ASSERT(sourceDesc.Format == destDesc.Format); + ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); + ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); + ASSERT(d3dFormatInfo.info().mipGenerationFunction != NULL); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result); + } + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, NULL, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + sourceSurface->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result); + } + + const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits); + uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits); + + ASSERT(sourceData && destData); + + d3dFormatInfo.info().mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, + sourceLocked.Pitch, 0, destData, destLocked.Pitch, + 0); + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) +{ + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = source->getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *destSurface = NULL; + error = dest->getSurface(&destSurface); + if (error.isError()) + { + return error; + } + + error = generateMip(destSurface, sourceSurface); + if (error.isError()) + { + return error; + } + + dest->markDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +{ + D3DLOCKED_RECT sourceLock = {0}; + D3DLOCKED_RECT destLock = {0}; + + HRESULT result; + + result = source->LockRect(&sourceLock, NULL, 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + } + + result = dest->LockRect(&destLock, NULL, 0); + if (FAILED(result)) + { + source->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + } + + ASSERT(sourceLock.pBits && destLock.pBits); + + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; + + unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); + ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) && + bytes <= static_cast<unsigned int>(destLock.Pitch)); + + for(unsigned int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + + return gl::Error(GL_NO_ERROR); +} + +bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(size.depth <= 1); + + // Only 2D and cube texture are supported by the D3D9 backend. + ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); + + if (mWidth != size.width || + mHeight != size.height || + mDepth != size.depth || + mInternalFormat != internalformat || + forceRelease) + { + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; + mInternalFormat = internalformat; + + // compute the d3d format that will be used + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mD3DFormat = d3d9FormatInfo.texFormat; + mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); + + SafeRelease(mSurface); + mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); + + return true; + } + + return false; +} + +gl::Error Image9::createSurface() +{ + if (mSurface) + { + return gl::Error(GL_NO_ERROR); + } + + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; + const D3DFORMAT d3dFormat = getD3DFormat(); + + if (mWidth != 0 && mHeight != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = mWidth; + GLsizei requestHeight = mHeight; + d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, + poolToUse, &newTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result); + } + + newTexture->GetSurfaceLevel(levelToFetch, &newSurface); + SafeRelease(newTexture); + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + if (d3dFormatInfo.dataInitializerFunction != NULL) + { + RECT entireRect; + entireRect.left = 0; + entireRect.right = mWidth; + entireRect.top = 0; + entireRect.bottom = mHeight; + + D3DLOCKED_RECT lockedRect; + result = newSurface->LockRect(&lockedRect, &entireRect, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } + + d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits), + lockedRect.Pitch, 0); + + result = newSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result); + } + } + } + + mSurface = newSurface; + mDirty = false; + mD3DPool = poolToUse; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + if (mSurface) + { + HRESULT result = mSurface->LockRect(lockedRect, &rect, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } + + mDirty = true; + } + + return gl::Error(GL_NO_ERROR); +} + +void Image9::unlock() +{ + if (mSurface) + { + HRESULT result = mSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + } +} + +D3DFORMAT Image9::getD3DFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mD3DFormat != D3DFMT_UNKNOWN); + + return mD3DFormat; +} + +bool Image9::isDirty() const +{ + // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet + // if initialization is required before use. + return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; +} + +gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + *outSurface = mSurface; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) +{ + IDirect3DSurface9 *surface = NULL; + TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); + gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); +} + +gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) +{ + IDirect3DSurface9 *surface = NULL; + TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); + gl::Error error = + storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); +} + +gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface) +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + ASSERT(desc.Pool == D3DPOOL_MANAGED); + + if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) + { + if (mSurface) + { + gl::Error error = copyLockableSurfaces(surface, mSurface); + SafeRelease(mSurface); + if (error.isError()) + { + return error; + } + } + + mSurface = surface; + mD3DPool = desc.Pool; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); + + IDirect3DSurface9 *destSurface = NULL; + + if (index.type == GL_TEXTURE_2D) + { + error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface); + if (error.isError()) + { + return error; + } + } + else + { + ASSERT(gl::IsCubeMapTextureTarget(index.type)); + error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface); + if (error.isError()) + { + return error; + } + } + + error = copyToSurface(destSurface, region); + SafeRelease(destSurface); + return error; +} + +gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area) +{ + ASSERT(area.width > 0 && area.height > 0 && area.depth == 1); + ASSERT(destSurface); + + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } + + ASSERT(sourceSurface && sourceSurface != destSurface); + + RECT rect; + rect.left = area.x; + rect.top = area.y; + rect.right = area.x + area.width; + rect.bottom = area.y + area.height; + + POINT point = {rect.left, rect.top}; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (mD3DPool == D3DPOOL_MANAGED) + { + D3DSURFACE_DESC desc; + sourceSurface->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result); + } + + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + SafeRelease(surf); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + else + { + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +gl::Error Image9::loadData(const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum inputType, + const void *input, + bool applySkipImages) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(area.z == 0 && area.depth == 1); + ASSERT(getSizedInputFormat(inputType) == mInternalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLuint inputRowPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeRowPitch(area.width, unpack.alignment, unpack.rowLength), + inputRowPitch); + ASSERT(!applySkipImages); + ASSERT(unpack.skipPixels == 0); + ASSERT(unpack.skipRows == 0); + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + ASSERT(d3dFormatInfo.loadFunction != NULL); + + RECT lockRect = + { + area.x, area.y, + area.x + area.width, area.y + area.height + }; + + D3DLOCKED_RECT locked; + gl::Error error = lock(&locked, lockRect); + if (error.isError()) + { + return error; + } + + d3dFormatInfo.loadFunction(area.width, area.height, area.depth, + reinterpret_cast<const uint8_t *>(input), inputRowPitch, 0, + reinterpret_cast<uint8_t *>(locked.pBits), locked.Pitch, 0); + + unlock(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(area.z == 0 && area.depth == 1); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputDepthPitch), + inputDepthPitch); + + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + + ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); + ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); + + ASSERT(d3d9FormatInfo.loadFunction != NULL); + + RECT lockRect = + { + area.x, area.y, + area.x + area.width, area.y + area.height + }; + + D3DLOCKED_RECT locked; + gl::Error error = lock(&locked, lockRect); + if (error.isError()) + { + return error; + } + + d3d9FormatInfo.loadFunction(area.width, area.height, area.depth, + reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, + reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); + + unlock(); + + return gl::Error(GL_NO_ERROR); +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + RenderTargetD3D *source) +{ + ASSERT(source); + + // ES3.0 only behaviour to copy into a 3d texture + ASSERT(destOffset.z == 0); + + RenderTarget9 *renderTarget = GetAs<RenderTarget9>(source); + + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + IDirect3DSurface9 *renderTargetData = NULL; + D3DSURFACE_DESC description; + surface->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + + if (FAILED(result)) + { + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result); + } + + result = device->GetRenderTargetData(surface, renderTargetData); + + if (FAILED(result)) + { + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result); + } + + int width = sourceArea.width; + int height = sourceArea.height; + + RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height }; + RECT destRect = { destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height }; + + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result); + } + + D3DLOCKED_RECT destLock = {0}; + gl::Error error = lock(&destLock, destRect); + if (error.isError()) + { + renderTargetData->UnlockRect(); + SafeRelease(renderTargetData); + SafeRelease(surface); + return error; + } + + ASSERT(destLock.pBits && sourceLock.pBits); + + unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits; + unsigned char *destPixels = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch (getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + for (int y = 0; y < height; y++) + { + memcpy(destPixels, sourcePixels, 4 * width); + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + destPixels[x] = sourcePixels[x * 4 + 2]; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2]; + destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3]; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch (getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short rgb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = static_cast<unsigned char>((rgb & 0xF800) >> 8); + unsigned char green = static_cast<unsigned char>((rgb & 0x07E0) >> 3); + unsigned char blue = static_cast<unsigned char>((rgb & 0x001F) << 3); + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 6); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0xF8; + destPixels[x] = red | (red >> 5); + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch (getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7); + unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2); + unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3); + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7); + unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2); + unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3); + unsigned char alpha = (signed short)argb >> 15; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = alpha; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x] = (red << 1) | (red >> 4); + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x * 2 + 0] = (red << 1) | (red >> 4); + destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + + unlock(); + renderTargetData->UnlockRect(); + + SafeRelease(renderTargetData); + SafeRelease(surface); + + mDirty = true; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) +{ + RenderTargetD3D *renderTarget = nullptr; + gl::Error error = source->getRenderTarget(imageIndex, &renderTarget); + if (error.isError()) + { + return error; + } + + gl::Rectangle sourceArea(0, 0, mWidth, mHeight); + return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget); +} + +gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + const gl::FramebufferAttachment *srcAttachment = source->getReadColorbuffer(); + ASSERT(srcAttachment); + + RenderTargetD3D *renderTarget = NULL; + gl::Error error = srcAttachment->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(renderTarget); + return copyFromRTInternal(destOffset, sourceArea, renderTarget); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h new file mode 100755 index 000000000..068a67fc9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-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. +// + +// Image9.h: Defines the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ + +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer9; + +class Image9 : public ImageD3D +{ + public: + Image9(Renderer9 *renderer); + ~Image9(); + + static gl::Error generateMipmap(Image9 *dest, Image9 *source); + static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; + + D3DFORMAT getD3DFormat() const; + + virtual bool isDirty() const; + + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level); + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level); + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + + gl::Error loadData(const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) override; + gl::Error loadCompressedData(const gl::Box &area, const void *input) override; + + gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + private: + gl::Error getSurface(IDirect3DSurface9 **outSurface); + + gl::Error createSurface(); + gl::Error setManagedSurface(IDirect3DSurface9 *surface); + gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area); + + gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect); + void unlock(); + + gl::Error copyFromRTInternal(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + RenderTargetD3D *source); + + Renderer9 *mRenderer; + + D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. + D3DFORMAT mD3DFormat; + + IDirect3DSurface9 *mSurface; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp new file mode 100755 index 000000000..40152df25 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -0,0 +1,167 @@ +// +// Copyright (c) 2002-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. +// + +// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. + +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) +{ + mIndexBuffer = NULL; + mBufferSize = 0; + mIndexType = 0; + mDynamic = false; +} + +IndexBuffer9::~IndexBuffer9() +{ + SafeRelease(mIndexBuffer); +} + +gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mIndexBuffer); + + updateSerial(); + + if (bufferSize > 0) + { + D3DFORMAT format = D3DFMT_UNKNOWN; + if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) + { + format = D3DFMT_INDEX16; + } + else if (indexType == GL_UNSIGNED_INT) + { + ASSERT(mRenderer->getNativeExtensions().elementIndexUint); + format = D3DFMT_INDEX32; + } + else UNREACHABLE(); + + DWORD usageFlags = D3DUSAGE_WRITEONLY; + if (dynamic) + { + usageFlags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamic = dynamic; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); + } + + *outMappedMemory = mapPtr; + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer9::unmapBuffer() +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum IndexBuffer9::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamic); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error IndexBuffer9::discard() +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + void *dummy; + HRESULT result; + + result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); + } + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +D3DFORMAT IndexBuffer9::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; + case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; + case GL_UNSIGNED_INT: return D3DFMT_INDEX32; + default: UNREACHABLE(); return D3DFMT_UNKNOWN; + } +} + +IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const +{ + return mIndexBuffer; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h new file mode 100755 index 000000000..ba03ba703 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2002-2012 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. +// + +// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ + +#include "libANGLE/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer9; + +class IndexBuffer9 : public IndexBuffer +{ + public: + explicit IndexBuffer9(Renderer9 *const renderer); + virtual ~IndexBuffer9(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual gl::Error unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + + virtual gl::Error discard(); + + D3DFORMAT getIndexFormat() const; + IDirect3DIndexBuffer9 *getBuffer() const; + + private: + Renderer9 *const mRenderer; + + IDirect3DIndexBuffer9 *mIndexBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamic; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp new file mode 100755 index 000000000..388b8aa16 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow9.cpp: Defines NativeWindow9, a class for managing and +// performing operations on an EGLNativeWindowType for the D3D9 renderer. + +#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h" + +namespace rx +{ +NativeWindow9::NativeWindow9(EGLNativeWindowType window) : NativeWindowD3D(window) +{ +} + +bool NativeWindow9::initialize() +{ + return true; +} + +bool NativeWindow9::getClientRect(LPRECT rect) const +{ + return GetClientRect(getNativeWindow(), rect) == TRUE; +} + +bool NativeWindow9::isIconic() const +{ + return IsIconic(getNativeWindow()) == TRUE; +} + +// static +bool NativeWindow9::IsValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h new file mode 100755 index 000000000..a56b08dc8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow9.h: Defines NativeWindow9, a class for managing and +// performing operations on an EGLNativeWindowType for the D3D9 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" + +namespace rx +{ + +class NativeWindow9 : public NativeWindowD3D +{ + public: + explicit NativeWindow9(EGLNativeWindowType window); + + bool initialize() override; + bool getClientRect(LPRECT rect) const override; + bool isIconic() const override; + + static bool IsValidNativeWindow(EGLNativeWindowType window); +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp new file mode 100755 index 000000000..9e5a90a2f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -0,0 +1,189 @@ +// +// Copyright (c) 2013 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. +// + +// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. + +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +#include <GLES2/gl2ext.h> + +namespace rx +{ +Query9::Query9(Renderer9 *renderer, GLenum type) + : QueryImpl(type), + mResult(GL_FALSE), + mQueryFinished(false), + mRenderer(renderer), + mQuery(NULL) +{ +} + +Query9::~Query9() +{ + SafeRelease(mQuery); +} + +gl::Error Query9::begin() +{ + D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType()); + if (mQuery == nullptr) + { + HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); + } + } + + if (d3dQueryType != D3DQUERYTYPE_EVENT) + { + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.", + result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::end() +{ + ASSERT(mQuery); + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result); + } + + mQueryFinished = false; + mResult = GL_FALSE; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::queryCounter() +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Unimplemented"); +} + +template <typename T> +gl::Error Query9::getResultBase(T *params) +{ + while (!mQueryFinished) + { + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + if (!mQueryFinished) + { + Sleep(0); + } + } + + ASSERT(mQueryFinished); + *params = static_cast<T>(mResult); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query9::isResultAvailable(bool *available) +{ + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + *available = mQueryFinished; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::testQuery() +{ + if (!mQueryFinished) + { + ASSERT(mQuery); + + HRESULT result = S_OK; + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + { + DWORD numPixels = 0; + result = mQuery->GetData(&numPixels, sizeof(numPixels), D3DGETDATA_FLUSH); + if (result == S_OK) + { + mQueryFinished = true; + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + } + break; + } + + case GL_COMMANDS_COMPLETED_CHROMIUM: + { + BOOL completed = FALSE; + result = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH); + if (result == S_OK) + { + mQueryFinished = true; + mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; + } + break; + } + + default: + UNREACHABLE(); + break; + } + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + else if (mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h new file mode 100755 index 000000000..9d17711a0 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2013 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. +// + +// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ + +#include "libANGLE/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer9; + +class Query9 : public QueryImpl +{ + public: + Query9(Renderer9 *renderer, GLenum type); + virtual ~Query9(); + + virtual gl::Error begin(); + virtual gl::Error end(); + virtual gl::Error queryCounter(); + virtual gl::Error getResult(GLint *params); + virtual gl::Error getResult(GLuint *params); + virtual gl::Error getResult(GLint64 *params); + virtual gl::Error getResult(GLuint64 *params); + virtual gl::Error isResultAvailable(bool *available); + + private: + gl::Error testQuery(); + + template <typename T> + gl::Error getResultBase(T *params); + + GLuint64 mResult; + bool mQueryFinished; + + Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp new file mode 100755 index 000000000..3e54c27f4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp @@ -0,0 +1,163 @@ +// +// 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. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +namespace rx +{ + +// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. +TextureRenderTarget9::TextureRenderTarget9(IDirect3DBaseTexture9 *texture, + size_t textureLevel, + IDirect3DSurface9 *surface, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mD3DFormat(D3DFMT_UNKNOWN), + mSamples(samples), + mTexture(texture), + mTextureLevel(textureLevel), + mRenderTarget(surface) +{ + ASSERT(mDepth == 1); + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + mD3DFormat = description.Format; + } +} + +TextureRenderTarget9::~TextureRenderTarget9() +{ + SafeRelease(mTexture); + SafeRelease(mRenderTarget); +} + +GLsizei TextureRenderTarget9::getWidth() const +{ + return mWidth; +} + +GLsizei TextureRenderTarget9::getHeight() const +{ + return mHeight; +} + +GLsizei TextureRenderTarget9::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget9::getInternalFormat() const +{ + return mInternalFormat; +} + +GLsizei TextureRenderTarget9::getSamples() const +{ + return mSamples; +} + +IDirect3DBaseTexture9 *TextureRenderTarget9::getTexture() const +{ + return mTexture; +} + +size_t TextureRenderTarget9::getTextureLevel() const +{ + return mTextureLevel; +} + +IDirect3DSurface9 *TextureRenderTarget9::getSurface() const +{ + // Caller is responsible for releasing the returned surface reference. + // TODO: remove the AddRef to match RenderTarget11 + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +D3DFORMAT TextureRenderTarget9::getD3DFormat() const +{ + return mD3DFormat; +} + +SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth) + : mSwapChain(swapChain), + mDepth(depth) +{ +} + +SurfaceRenderTarget9::~SurfaceRenderTarget9() +{ +} + +GLsizei SurfaceRenderTarget9::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget9::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget9::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget9::getInternalFormat() const +{ + return (mDepth ? mSwapChain->getDepthBufferInternalFormat() + : mSwapChain->getRenderTargetInternalFormat()); +} + +GLsizei SurfaceRenderTarget9::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() const +{ + return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); +} + +IDirect3DBaseTexture9 *SurfaceRenderTarget9::getTexture() const +{ + return (mDepth ? nullptr : mSwapChain->getOffscreenTexture()); +} + +size_t SurfaceRenderTarget9::getTextureLevel() const +{ + return 0; +} + +D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const +{ + return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h new file mode 100755 index 000000000..f19c54de7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h @@ -0,0 +1,98 @@ +// +// Copyright (c) 2012 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. +// + +// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers +// retained by Renderbuffers. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; + +class RenderTarget9 : public RenderTargetD3D +{ + public: + RenderTarget9() { } + virtual ~RenderTarget9() { } + // Retrieve the texture that backs this render target, may be null for swap chain render + // targets. + virtual IDirect3DBaseTexture9 *getTexture() const = 0; + virtual size_t getTextureLevel() const = 0; + + virtual IDirect3DSurface9 *getSurface() const = 0; + + virtual D3DFORMAT getD3DFormat() const = 0; +}; + +class TextureRenderTarget9 : public RenderTarget9 +{ + public: + TextureRenderTarget9(IDirect3DBaseTexture9 *texture, + size_t textureLevel, + IDirect3DSurface9 *surface, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + virtual ~TextureRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + IDirect3DBaseTexture9 *getTexture() const override; + size_t getTextureLevel() const override; + IDirect3DSurface9 *getSurface() const override; + + D3DFORMAT getD3DFormat() const override; + + private: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + D3DFORMAT mD3DFormat; + GLsizei mSamples; + + IDirect3DBaseTexture9 *mTexture; + size_t mTextureLevel; + IDirect3DSurface9 *mRenderTarget; +}; + +class SurfaceRenderTarget9 : public RenderTarget9 +{ + public: + SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth); + virtual ~SurfaceRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + IDirect3DBaseTexture9 *getTexture() const override; + size_t getTextureLevel() const override; + IDirect3DSurface9 *getSurface() const override; + + D3DFORMAT getD3DFormat() const override; + + private: + SwapChain9 *mSwapChain; + bool mDepth; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp new file mode 100755 index 000000000..d578d4075 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -0,0 +1,3032 @@ +// +// 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. +// + +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. + +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +#include <sstream> +#include <EGL/eglext.h> + +#include "common/utilities.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Context9.h" +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h" +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.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/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "third_party/trace_event/trace_event.h" + + + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2. +// Such a device would not be conformant. +#ifndef ANGLE_SUPPORT_SHADER_MODEL_2 +#define ANGLE_SUPPORT_SHADER_MODEL_2 0 +#endif + +namespace rx +{ + +enum +{ + MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, + MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, + MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, + MAX_VARYING_VECTORS_SM2 = 8, + MAX_VARYING_VECTORS_SM3 = 10, + + MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 +}; + +Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this) +{ + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + mBlit = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + const egl::AttributeMap &attributes = display->getAttributeMap(); + EGLint requestedDeviceType = static_cast<EGLint>(attributes.get( + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE)); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mDeviceType = D3DDEVTYPE_HAL; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDeviceType = D3DDEVTYPE_REF; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDeviceType = D3DDEVTYPE_NULLREF; + break; + + default: + UNREACHABLE(); + } + + mMaskedClearSavedState = NULL; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mLineLoopIB = NULL; + mCountingIB = NULL; + + mMaxNullColorbufferLRU = 0; + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + mNullColorbufferCache[i].lruCount = 0; + mNullColorbufferCache[i].width = 0; + mNullColorbufferCache[i].height = 0; + mNullColorbufferCache[i].buffer = NULL; + } + + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; + + gl::InitializeDebugAnnotations(&mAnnotator); + + mEGLDevice = nullptr; +} + +Renderer9::~Renderer9() +{ + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (testDeviceLost()) + { + resetDevice(); + } + } + + release(); +} + +void Renderer9::release() +{ + RendererD3D::cleanup(); + + gl::UninitializeDebugAnnotations(); + + mTranslatedAttribCache.clear(); + + releaseDeviceResources(); + + SafeDelete(mEGLDevice); + SafeRelease(mDevice); + SafeRelease(mDeviceEx); + SafeRelease(mD3d9); + SafeRelease(mD3d9Ex); + + mCompiler.release(); + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + mD3d9Module = NULL; +} + +egl::Error Renderer9::initialize() +{ + TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9"); + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + + if (mD3d9Module == NULL) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found."); + } + + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + // Use Direct3D9Ex if available. Among other things, this version is less + // inclined to report a lost context, for example when the user switches + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. + if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface"); + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9)); + ASSERT(mD3d9); + } + else + { + TRACE_EVENT0("gpu.angle", "Direct3DCreate9"); + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (!mD3d9) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device."); + } + + if (mDisplay->getNativeDisplayId() != nullptr) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + { + TRACE_EVENT0("gpu.angle", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_OTHER_ERROR, + "Failed to get device caps: Error code 0x%x\n", result); + } + } + } + +#if ANGLE_SUPPORT_SHADER_MODEL_2 + size_t minShaderModel = 2; +#else + size_t minShaderModel = 3; +#endif + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_VERSION, + "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0); + } + + // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. + // This is required by Texture2D::ensureRenderTarget. + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + "Renderer does not support StretctRect from textures."); + } + + { + TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier"); + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + } + + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); + static const TCHAR className[] = TEXT("STATIC"); + + { + TRACE_EVENT0("gpu.angle", "CreateWindowEx"); + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + } + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED; + + { + TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + } + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice failed: device lost of out of memory"); + } + + if (FAILED(result)) + { + TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice2 failed: device lost, not available, or of out of memory"); + } + } + + if (mD3d9Ex) + { + TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface"); + result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + { + TRACE_EVENT0("gpu.angle", "ShaderCache initialize"); + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + } + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Check vertex texture support + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); + + initializeDevice(); + + return egl::Error(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 Renderer9::initializeDevice() +{ + // Permanent non-default states + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); + + if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); + } + else + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f + } + + const gl::Caps &rendererCaps = getNativeCaps(); + + mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + + mCurVertexTextures.resize(rendererCaps.maxVertexTextureImageUnits); + mCurPixelTextures.resize(rendererCaps.maxTextureImageUnits); + + markAllStateDirty(); + + mSceneStarted = false; + + ASSERT(!mBlit); + mBlit = new Blit9(this); + mBlit->initialize(); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this, getRendererClass()); + + mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes); + + mStateManager.initialize(); +} + +D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() +{ + D3DPRESENT_PARAMETERS presentParameters = {0}; + + // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. + presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferWidth = 1; + presentParameters.BackBufferHeight = 1; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mDeviceWindow; + presentParameters.MultiSampleQuality = 0; + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; + presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + + return presentParameters; +} + +egl::ConfigSet Renderer9::generateConfigs() +{ + static const GLenum colorBufferFormats[] = + { + GL_BGR5_A1_ANGLEX, + GL_BGRA8_EXT, + GL_RGB565, + + }; + + static const GLenum depthStencilBufferFormats[] = + { + GL_NONE, + GL_DEPTH_COMPONENT32_OES, + GL_DEPTH24_STENCIL8_OES, + GL_DEPTH_COMPONENT24_OES, + GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getNativeCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Determine the min and max swap intervals + int minSwapInterval = 4; + int maxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + minSwapInterval = std::min(minSwapInterval, 0); + maxSwapInterval = std::max(maxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + minSwapInterval = std::min(minSwapInterval, 1); + maxSwapInterval = std::max(maxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + minSwapInterval = std::min(minSwapInterval, 2); + maxSwapInterval = std::max(maxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + minSwapInterval = std::min(minSwapInterval, 3); + maxSwapInterval = std::max(maxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + minSwapInterval = std::min(minSwapInterval, 4); + maxSwapInterval = std::max(maxSwapInterval, 4); + } + + egl::ConfigSet configs; + for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) + { + GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; + const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + if (colorBufferFormatCaps.renderable) + { + for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) + { + GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; + const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) + { + const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + const d3d9::TextureFormat &d3d9ColorBufferFormatInfo = d3d9::GetTextureFormatInfo(colorBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + // Mark as slow if blits to the back-buffer won't be straight forward + config.configCaveat = (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + config.configID = static_cast<EGLint>(configs.size() + 1); + config.conformant = EGL_OPENGL_ES2_BIT; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = maxSwapInterval; + config.minSwapInterval = minSwapInterval; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + config.renderableType = EGL_OPENGL_ES2_BIT; + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); + } + } + } + } + + ASSERT(configs.size() > 0); + return configs; +} + +void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + if (getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + outExtensions->d3dTextureClientBuffer = true; + + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + outExtensions->postSubBuffer = true; + outExtensions->deviceQuery = true; + + outExtensions->image = true; + outExtensions->imageBase = true; + outExtensions->glTexture2DImage = true; + outExtensions->glRenderbufferImage = true; + + outExtensions->flexibleSurfaceCompatibility = true; +} + +void Renderer9::startScene() +{ + if (!mSceneStarted) + { + long result = mDevice->BeginScene(); + if (SUCCEEDED(result)) { + // This is defensive checking against the device being + // lost at unexpected times. + mSceneStarted = true; + } + } +} + +void Renderer9::endScene() +{ + if (mSceneStarted) + { + // EndScene can fail if the device was lost, for example due + // to a TDR during a draw call. + mDevice->EndScene(); + mSceneStarted = false; + } +} + +gl::Error Renderer9::flush() +{ + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) + { + return error; + } + + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + freeEventQuery(query); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::finish() +{ + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) + { + return error; + } + + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + // Loop until the query completes + while (result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + ScheduleYield(); + + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (result == S_FALSE && testDeviceLost()) + { + result = D3DERR_DEVICELOST; + } + + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + } + + freeEventQuery(query); + + return gl::Error(GL_NO_ERROR); +} + +bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const +{ + return NativeWindow9::IsValidNativeWindow(window); +} + +NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window, + const egl::Config *, + const egl::AttributeMap &) const +{ + return new NativeWindow9(window); +} + +SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) +{ + return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture, + backBufferFormat, depthBufferFormat, orientation); +} + +egl::Error Renderer9::getD3DTextureInfo(IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const +{ + IDirect3DTexture9 *texture = nullptr; + if (FAILED(d3dTexture->QueryInterface(&texture))) + { + return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a IDirect3DTexture9"); + } + + IDirect3DDevice9 *textureDevice = nullptr; + texture->GetDevice(&textureDevice); + if (textureDevice != mDevice) + { + SafeRelease(texture); + return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match."); + } + SafeRelease(textureDevice); + + D3DSURFACE_DESC desc; + texture->GetLevelDesc(0, &desc); + SafeRelease(texture); + + if (width) + { + *width = static_cast<EGLint>(desc.Width); + } + if (height) + { + *height = static_cast<EGLint>(desc.Height); + } + + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (desc.Format) + { + case D3DFMT_R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + break; + + default: + return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", + desc.Format); + } + + if (fboFormat) + { + const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE); + *fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error Renderer9::validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const +{ + if (shareHandle == nullptr) + { + return egl::Error(EGL_BAD_PARAMETER, "NULL share handle."); + } + + EGLint width = attribs.getAsInt(EGL_WIDTH, 0); + EGLint height = attribs.getAsInt(EGL_HEIGHT, 0); + ASSERT(width != 0 && height != 0); + + const d3d9::TextureFormat &backBufferd3dFormatInfo = + d3d9::GetTextureFormatInfo(config->renderTargetFormat); + + IDirect3DTexture9 *texture = nullptr; + HRESULT result = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, + backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, + &texture, &shareHandle); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result); + } + + DWORD levelCount = texture->GetLevelCount(); + + D3DSURFACE_DESC desc; + texture->GetLevelDesc(0, &desc); + SafeRelease(texture); + + if (levelCount != 1 || desc.Width != static_cast<UINT>(width) || + desc.Height != static_cast<UINT>(height) || + desc.Format != backBufferd3dFormatInfo.texFormat) + { + return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture."); + } + + return egl::Error(EGL_SUCCESS); +} + +ContextImpl *Renderer9::createContext(const gl::ContextState &state) +{ + return new Context9(state, this); +} + +void *Renderer9::getD3DDevice() +{ + return reinterpret_cast<void*>(mDevice); +} + +gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) +{ + if (mEventQueryPool.empty()) + { + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result); + } + } + else + { + *outQuery = mEventQueryPool.back(); + mEventQueryPool.pop_back(); + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::freeEventQuery(IDirect3DQuery9* query) +{ + if (mEventQueryPool.size() > 1000) + { + SafeRelease(query); + } + else + { + mEventQueryPool.push_back(query); + } +} + +gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader) +{ + return mVertexShaderCache.create(function, length, outShader); +} + +gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader) +{ + return mPixelShaderCache.create(function, length, outShader); +} + +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); +} + +VertexBuffer *Renderer9::createVertexBuffer() +{ + return new VertexBuffer9(this); +} + +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); +} + +IndexBuffer *Renderer9::createIndexBuffer() +{ + return new IndexBuffer9(this); +} + +StreamProducerImpl *Renderer9::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) +{ + // Streams are not supported under D3D9 + UNREACHABLE(); + return nullptr; +} + +bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + return false; +} + +gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) +{ + CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates[index] + : mCurVertexSamplerStates[index]; + + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } + + // Storage should exist, texture should be complete + ASSERT(storage); + + DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel(); + + if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel || + memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0) + { + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); + + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; + float lodBias; + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, &lodBias, + samplerState.maxAnisotropy, baseLevel); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias)); + if (getNativeExtensions().textureFilterAnisotropic) + { + DWORD maxAnisotropy = + std::min(mDeviceCaps.MaxAnisotropy, static_cast<DWORD>(samplerState.maxAnisotropy)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy); + } + } + + appliedSampler.forceSet = false; + appliedSampler.samplerState = samplerState; + appliedSampler.baseLevel = baseLevel; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + IDirect3DBaseTexture9 *d3dTexture = NULL; + bool forceSetTexture = false; + + std::vector<uintptr_t> &appliedTextures = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = nullptr; + gl::Error error = textureImpl->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage); + error = storage9->getBaseTexture(&d3dTexture); + if (error.isError()) + { + return error; + } + + // If we get NULL back from getBaseTexture here, something went wrong + // in the texture class and we're unexpectedly missing the d3d texture + ASSERT(d3dTexture != NULL); + + forceSetTexture = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); + } + + if (forceSetTexture || appliedTextures[index] != reinterpret_cast<uintptr_t>(d3dTexture)) + { + mDevice->SetTexture(d3dSampler, d3dTexture); + } + + appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::setUniformBuffers(const gl::ContextState & /*data*/, + const std::vector<GLint> & /*vertexUniformBuffers*/, + const std::vector<GLint> & /*fragmentUniformBuffers*/) +{ + // No effect in ES2/D3D9 + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode) +{ + const auto &data = context->getContextState(); + const auto &glState = data.getState(); + + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data)); + + ANGLE_TRY(applyRenderTarget(context, framebuffer)); + + // Setting viewport state + setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode, + glState.getRasterizerState().frontFace, false); + + // Setting scissors state + setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); + + // Setting blend, depth stencil, and rasterizer states + // Since framebuffer->getSamples will return the original samples which may be different with + // the sample counts that we set in render target view, here we use renderTarget->getSamples to + // get the actual samples. + GLsizei samples = 0; + auto firstColorAttachment = framebuffer->getFirstColorbuffer(); + if (firstColorAttachment) + { + ASSERT(firstColorAttachment->isAttached()); + RenderTarget9 *renderTarget = nullptr; + ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget)); + samples = renderTarget->getSamples(); + } + gl::RasterizerState rasterizer = glState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + unsigned int mask = GetBlendSampleMask(data, samples); + ANGLE_TRY(setBlendDepthRasterStates(data, mask)); + + mStateManager.resetDirtyBits(); + + return gl::NoError(); +} + +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + mStateManager.setScissorState(scissor, enabled); +} + +gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode) +{ + const auto &glState = glData.getState(); + auto drawFramebuffer = glState.getDrawFramebuffer(); + ASSERT(!drawFramebuffer->hasAnyDirtyBit()); + // Since framebuffer->getSamples will return the original samples which may be different with + // the sample counts that we set in render target view, here we use renderTarget->getSamples to + // get the actual samples. + GLsizei samples = 0; + auto firstColorAttachment = drawFramebuffer->getFirstColorbuffer(); + if (firstColorAttachment) + { + ASSERT(firstColorAttachment->isAttached()); + RenderTarget9 *renderTarget = nullptr; + ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget)); + samples = renderTarget->getSamples(); + } + gl::RasterizerState rasterizer = glState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + unsigned int mask = GetBlendSampleMask(glData, samples); + return mStateManager.setBlendDepthRasterStates(glState, mask); +} + +void Renderer9::setViewport(const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport) +{ + mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport); +} + +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) +{ + switch (mode) + { + case GL_POINTS: + mPrimitiveType = D3DPT_POINTLIST; + mPrimitiveCount = count; + break; + case GL_LINES: + mPrimitiveType = D3DPT_LINELIST; + mPrimitiveCount = count / 2; + break; + case GL_LINE_LOOP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately + break; + case GL_LINE_STRIP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; + break; + case GL_TRIANGLES: + mPrimitiveType = D3DPT_TRIANGLELIST; + mPrimitiveCount = count / 3; + break; + case GL_TRIANGLE_STRIP: + mPrimitiveType = D3DPT_TRIANGLESTRIP; + mPrimitiveCount = count - 2; + break; + case GL_TRIANGLE_FAN: + mPrimitiveType = D3DPT_TRIANGLEFAN; + mPrimitiveCount = count - 2; + break; + default: + UNREACHABLE(); + return false; + } + + return mPrimitiveCount > 0; +} + +gl::Error Renderer9::getNullColorbuffer(GLImplFactory *implFactory, + const gl::FramebufferAttachment *depthbuffer, + const gl::FramebufferAttachment **outColorBuffer) +{ + ASSERT(depthbuffer); + + const gl::Extents &size = depthbuffer->getSize(); + + // search cached nullcolorbuffers + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].buffer != NULL && + mNullColorbufferCache[i].width == size.width && + mNullColorbufferCache[i].height == size.height) + { + mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; + *outColorBuffer = mNullColorbufferCache[i].buffer; + return gl::Error(GL_NO_ERROR); + } + } + + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0); + gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height); + if (error.isError()) + { + SafeDelete(nullRenderbuffer); + return error; + } + + gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer); + + // add nullbuffer to the cache + NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; + for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].lruCount < oldest->lruCount) + { + oldest = &mNullColorbufferCache[i]; + } + } + + delete oldest->buffer; + oldest->buffer = nullbuffer; + oldest->lruCount = ++mMaxNullColorbufferLRU; + oldest->width = size.width; + oldest->height = size.height; + + *outColorBuffer = nullbuffer; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory, + const gl::FramebufferAttachment *colorAttachment, + const gl::FramebufferAttachment *depthStencilAttachment) +{ + const gl::FramebufferAttachment *renderAttachment = colorAttachment; + gl::Error error(GL_NO_ERROR); + + // if there is no color attachment we must synthesize a NULL colorattachment + // to keep the D3D runtime happy. This should only be possible if depth texturing. + if (renderAttachment == nullptr) + { + error = getNullColorbuffer(implFactory, depthStencilAttachment, &renderAttachment); + if (error.isError()) + { + return error; + } + } + ASSERT(renderAttachment != nullptr); + + size_t renderTargetWidth = 0; + size_t renderTargetHeight = 0; + D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN; + + RenderTarget9 *renderTarget = nullptr; + error = renderAttachment->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + bool renderTargetChanged = false; + unsigned int renderTargetSerial = renderTarget->getSerial(); + if (renderTargetSerial != mAppliedRenderTargetSerial) + { + // Apply the render target on the device + IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface(); + ASSERT(renderTargetSurface); + + mDevice->SetRenderTarget(0, renderTargetSurface); + SafeRelease(renderTargetSurface); + + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getD3DFormat(); + + mAppliedRenderTargetSerial = renderTargetSerial; + renderTargetChanged = true; + } + + RenderTarget9 *depthStencilRenderTarget = nullptr; + unsigned int depthStencilSerial = 0; + + if (depthStencilAttachment != nullptr) + { + error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(depthStencilRenderTarget); + + depthStencilSerial = depthStencilRenderTarget->getSerial(); + } + + if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized) + { + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + + // Apply the depth stencil on the device + if (depthStencilRenderTarget) + { + IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface(); + ASSERT(depthStencilSurface); + + mDevice->SetDepthStencilSurface(depthStencilSurface); + SafeRelease(depthStencilSurface); + + depthSize = depthStencilAttachment->getDepthSize(); + stencilSize = depthStencilAttachment->getStencilSize(); + } + else + { + mDevice->SetDepthStencilSurface(NULL); + } + + mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize); + mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize); + + mAppliedDepthStencilSerial = depthStencilSerial; + mDepthStencilInitialized = true; + } + + if (renderTargetChanged || !mRenderTargetDescInitialized) + { + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight); + mRenderTargetDescInitialized = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory, + const gl::Framebuffer *framebuffer) +{ + return applyRenderTarget(implFactory, framebuffer->getColorbuffer(0), + framebuffer->getDepthOrStencilbuffer()); +} + +gl::Error Renderer9::applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData * /*indexInfo*/) +{ + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); + if (error.isError()) + { + return error; + } + + return mVertexDeclarationCache.applyDeclaration( + mDevice, mTranslatedAttribCache, state.getProgram(), first, instances, &mRepeatDraw); +} + +// Applies the indices and element array bindings to the Direct3D 9 device +gl::Error Renderer9::applyIndexBuffer(const gl::ContextState &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) +{ + gl::VertexArray *vao = data.getState().getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, + indexInfo, false); + if (error.isError()) + { + return error; + } + + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(indexInfo->storage == NULL); + + if (indexInfo->serial != mAppliedIBSerial) + { + IndexBuffer9* indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = indexInfo->serial; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyTransformFeedbackBuffers(const gl::State &state) +{ + ASSERT(!state.isTransformFeedbackActiveUnpaused()); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::drawArraysImpl(const gl::ContextState &data, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances) +{ + ASSERT(!data.getState().isTransformFeedbackActiveUnpaused()); + + startScene(); + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (instances > 0) + { + StaticIndexBufferInterface *countingIB = NULL; + gl::Error error = getCountingIB(count, &countingIB); + if (error.isError()) + { + return error; + } + + if (mAppliedIBSerial != countingIB->getSerial()) + { + IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(countingIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = countingIB->getSerial(); + } + + for (int i = 0; i < mRepeatDraw; i++) + { + mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); + } + + return gl::Error(GL_NO_ERROR); + } + else // Regular case + { + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error Renderer9::drawElementsImpl(const gl::ContextState &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei /*instances*/) +{ + startScene(); + + int minIndex = static_cast<int>(indexInfo.indexRange.start); + + gl::VertexArray *vao = data.getState().getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + if (mode == GL_POINTS) + { + return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); + } + else if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + } + else + { + size_t vertexCount = indexInfo.indexRange.vertexCount(); + for (int i = 0; i < mRepeatDraw; i++) + { + mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, + static_cast<UINT>(vertexCount), indexInfo.startIndex, + mPrimitiveCount); + } + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + indices = bufferData + offset; + } + + unsigned int startIndex = 0; + + if (getNativeExtensions().elementIndexUint) + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + } + + const unsigned int spaceNeeded = (static_cast<unsigned int>(count)+1) * sizeof(unsigned int); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset = 0; + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + startIndex = static_cast<unsigned int>(offset) / 4; + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLubyte*>(indices)[i]; + } + data[count] = static_cast<const GLubyte*>(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLushort*>(indices)[i]; + } + data[count] = static_cast<const GLushort*>(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLuint*>(indices)[i]; + } + data[count] = static_cast<const GLuint*>(indices)[0]; + break; + default: UNREACHABLE(); + } + + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + else + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + } + + const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset; + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + startIndex = static_cast<unsigned int>(offset) / 2; + unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = static_cast<unsigned short>(i); + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLubyte*>(indices)[i]; + } + data[count] = static_cast<const GLubyte*>(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLushort*>(indices)[i]; + } + data[count] = static_cast<const GLushort*>(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<unsigned short>(static_cast<const GLuint*>(indices)[i]); + } + data[count] = static_cast<unsigned short>(static_cast<const GLuint*>(indices)[0]); + break; + default: UNREACHABLE(); + } + + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial()) + { + IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(mLineLoopIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = mLineLoopIB->getSerial(); + } + + mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); + + return gl::Error(GL_NO_ERROR); +} + +template <typename T> +static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +{ + for (int i = 0; i < count; i++) + { + unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]) - minIndex; + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call + // for each individual point. This call is not expected to happen often. + + if (elementArrayBuffer) + { + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: return drawPoints<GLubyte>(mDevice, count, indices, minIndex); + case GL_UNSIGNED_SHORT: return drawPoints<GLushort>(mDevice, count, indices, minIndex); + case GL_UNSIGNED_INT: return drawPoints<GLuint>(mDevice, count, indices, minIndex); + default: UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); + } +} + +gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB) +{ + // Update the counting index buffer if it is not large enough or has not been created yet. + if (count <= 65536) // 16-bit indices + { + const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short); + + if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) + { + SafeDelete(mCountingIB); + mCountingIB = new StaticIndexBufferInterface(this); + mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + void *mappedMemory = NULL; + gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); + if (error.isError()) + { + return error; + } + + unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); + for (size_t i = 0; i < count; i++) + { + data[i] = static_cast<unsigned short>(i); + } + + error = mCountingIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + } + else if (getNativeExtensions().elementIndexUint) + { + const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int); + + if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) + { + SafeDelete(mCountingIB); + mCountingIB = new StaticIndexBufferInterface(this); + mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + + void *mappedMemory = NULL; + gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); + if (error.isError()) + { + return error; + } + + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); + for (unsigned int i = 0; i < count; i++) + { + data[i] = i; + } + + error = mCountingIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + } + else + { + return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced."); + } + + *outIB = mCountingIB; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyShaders(const gl::ContextState &data, GLenum drawMode) +{ + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram()); + programD3D->updateCachedInputLayout(data.getState()); + + const auto &inputLayout = programD3D->getCachedInputLayout(); + + ShaderExecutableD3D *vertexExe = NULL; + ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr)); + + const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer(); + ShaderExecutableD3D *pixelExe = NULL; + ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe)); + + IDirect3DVertexShader9 *vertexShader = (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr); + IDirect3DPixelShader9 *pixelShader = (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr); + + if (vertexShader != mAppliedVertexShader) + { + mDevice->SetVertexShader(vertexShader); + mAppliedVertexShader = vertexShader; + } + + if (pixelShader != mAppliedPixelShader) + { + mDevice->SetPixelShader(pixelShader); + mAppliedPixelShader = pixelShader; + } + + // D3D9 has a quirk where creating multiple shaders with the same content + // can return the same shader pointer. Because GL programs store different data + // per-program, checking the program serial guarantees we upload fresh + // uniform data even if our shader pointers are the same. + // https://code.google.com/p/angleproject/issues/detail?id=661 + unsigned int programSerial = programD3D->getSerial(); + if (programSerial != mAppliedProgramSerial) + { + programD3D->dirtyAllUniforms(); + mStateManager.forceSetDXUniformsState(); + mAppliedProgramSerial = programSerial; + } + + return programD3D->applyUniforms(drawMode); +} + +gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, + GLenum /*drawMode*/, + const std::vector<D3DUniform *> &uniformArray) +{ + for (const D3DUniform *targetUniform : uniformArray) + { + if (!targetUniform->dirty) + continue; + + GLfloat *f = (GLfloat *)targetUniform->data; + GLint *i = (GLint *)targetUniform->data; + + switch (targetUniform->type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + break; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + applyUniformnbv(targetUniform, i); + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + applyUniformnfv(targetUniform, f); + break; + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + applyUniformniv(targetUniform, i); + break; + default: + UNREACHABLE(); + } + } + + // Driver uniforms + mStateManager.setShaderConstants(); + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v) +{ + if (targetUniform->isReferencedByFragmentShader()) + { + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + } + + if (targetUniform->isReferencedByVertexShader()) + { + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + } +} + +void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (GLfloat)v[4 * i + 0]; + vector[i][1] = (GLfloat)v[4 * i + 1]; + vector[i][2] = (GLfloat)v[4 * i + 2]; + vector[i][3] = (GLfloat)v[4 * i + 3]; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +gl::Error Renderer9::clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer) +{ + if (clearParams.colorClearType != GL_FLOAT) + { + // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + bool clearColor = clearParams.clearColor[0]; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + if (clearParams.clearColor[i] != clearColor) + { + // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + } + + float depth = gl::clamp01(clearParams.depthClearValue); + DWORD stencil = clearParams.stencilClearValue & 0x000000FF; + + unsigned int stencilUnmasked = 0x0; + if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0) + { + ASSERT(depthStencilBuffer != nullptr); + + RenderTargetD3D *stencilRenderTarget = nullptr; + gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget9 *stencilRenderTarget9 = GetAs<RenderTarget9>(stencilRenderTarget); + ASSERT(stencilRenderTarget9); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); + stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1; + } + + const bool needMaskedStencilClear = clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + bool needMaskedColorClear = false; + D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); + if (clearColor) + { + ASSERT(colorBuffer != nullptr); + + RenderTargetD3D *colorRenderTarget = NULL; + gl::Error error = colorBuffer->getRenderTarget(&colorRenderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget9 *colorRenderTarget9 = GetAs<RenderTarget9>(colorRenderTarget); + ASSERT(colorRenderTarget9); + + const gl::InternalFormat &formatInfo = *colorBuffer->getFormat().info; + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat()); + + color = + D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0) + ? 1.0f + : clearParams.colorFClearValue.alpha), + gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) + ? 0.0f + : clearParams.colorFClearValue.red), + gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) + ? 0.0f + : clearParams.colorFClearValue.green), + gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) + ? 0.0f + : clearParams.colorFClearValue.blue)); + + if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + needMaskedColorClear = true; + } + } + + if (needMaskedColorClear || needMaskedStencilClear) + { + // State which is altered in all paths from this point to the clear call is saved. + // State which is altered in only some paths will be flagged dirty in the case that + // that path is taken. + HRESULT hr; + if (mMaskedClearSavedState == NULL) + { + hr = mDevice->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); + mDevice->SetStreamSource(0, NULL, 0, 0); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + hr = mDevice->EndStateBlock(&mMaskedClearSavedState); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mMaskedClearSavedState != NULL); + + if (mMaskedClearSavedState != NULL) + { + hr = mMaskedClearSavedState->Capture(); + ASSERT(SUCCEEDED(hr)); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + + if (clearColor) + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, + clearParams.colorMaskGreen, + clearParams.colorMaskBlue, + clearParams.colorMaskAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + } + + if (stencilUnmasked != 0x0 && clearParams.clearStencil) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); + mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_STENCILREF, stencil); + mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); + mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + int renderTargetWidth = mStateManager.getRenderTargetWidth(); + int renderTargetHeight = mStateManager.getRenderTargetHeight(); + + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + quad[0][0] = -0.5f; + quad[0][1] = renderTargetHeight - 0.5f; + quad[0][2] = 0.0f; + quad[0][3] = 1.0f; + + quad[1][0] = renderTargetWidth - 0.5f; + quad[1][1] = renderTargetHeight - 0.5f; + quad[1][2] = 0.0f; + quad[1][3] = 1.0f; + + quad[2][0] = -0.5f; + quad[2][1] = -0.5f; + quad[2][2] = 0.0f; + quad[2][3] = 1.0f; + + quad[3][0] = renderTargetWidth - 0.5f; + quad[3][1] = -0.5f; + quad[3][2] = 0.0f; + quad[3][3] = 1.0f; + + startScene(); + mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); + + if (clearParams.clearDepth) + { + mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); + } + + if (mMaskedClearSavedState != NULL) + { + mMaskedClearSavedState->Apply(); + } + } + else if (clearColor || clearParams.clearDepth || clearParams.clearStencil) + { + DWORD dxClearFlags = 0; + if (clearColor) + { + dxClearFlags |= D3DCLEAR_TARGET; + } + if (clearParams.clearDepth) + { + dxClearFlags |= D3DCLEAR_ZBUFFER; + } + if (clearParams.clearStencil) + { + dxClearFlags |= D3DCLEAR_STENCIL; + } + + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::markAllStateDirty() +{ + mAppliedRenderTargetSerial = 0; + mAppliedDepthStencilSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + mStateManager.forceSetRasterState(); + mStateManager.forceSetDepthStencilState(); + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.forceSetViewportState(); + + ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size()); + for (unsigned int i = 0; i < mCurVertexTextures.size(); i++) + { + mCurVertexSamplerStates[i].forceSet = true; + mCurVertexTextures[i] = angle::DirtyPointer; + } + + ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size()); + for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++) + { + mCurPixelSamplerStates[i].forceSet = true; + mCurPixelTextures[i] = angle::DirtyPointer; + } + + mAppliedIBSerial = 0; + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; + mStateManager.forceSetDXUniformsState(); + + mVertexDeclarationCache.markStateDirty(); +} + +void Renderer9::releaseDeviceResources() +{ + for (size_t i = 0; i < mEventQueryPool.size(); i++) + { + SafeRelease(mEventQueryPool[i]); + } + mEventQueryPool.clear(); + + SafeRelease(mMaskedClearSavedState); + + mVertexShaderCache.clear(); + mPixelShaderCache.clear(); + + SafeDelete(mBlit); + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mCountingIB); + + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + SafeDelete(mNullColorbufferCache[i].buffer); + } +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer9::testDeviceLost() +{ + HRESULT status = getDeviceStatusCode(); + return FAILED(status); +} + +HRESULT Renderer9::getDeviceStatusCode() +{ + HRESULT status = D3D_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + + return status; +} + +bool Renderer9::testDeviceResettable() +{ + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted + // DEVICEREMOVED indicates the device has been stopped and must be recreated + switch (getDeviceStatusCode()) + { + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != NULL); + case D3DERR_DEVICEREMOVED: + ASSERT(mDeviceEx != NULL); + return isRemovedDeviceResettable(); + default: + return false; + } +} + +bool Renderer9::resetDevice() +{ + releaseDeviceResources(); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + + HRESULT result = D3D_OK; + bool lost = testDeviceLost(); + bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); + + // Device Removed is a feature which is only present with D3D9Ex + ASSERT(mDeviceEx != NULL || !removedDevice); + + for (int attempts = 3; lost && attempts > 0; attempts--) + { + if (removedDevice) + { + // Device removed, which may trigger on driver reinstallation, + // may cause a longer wait other reset attempts before the + // system is ready to handle creating a new device. + Sleep(800); + lost = !resetRemovedDevice(); + } + else if (mDeviceEx) + { + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, NULL); + lost = testDeviceLost(); + } + else + { + result = mDevice->TestCooperativeLevel(); + while (result == D3DERR_DEVICELOST) + { + Sleep(100); // Give the graphics driver some CPU time + result = mDevice->TestCooperativeLevel(); + } + + if (result == D3DERR_DEVICENOTRESET) + { + result = mDevice->Reset(&presentParameters); + } + lost = testDeviceLost(); + } + } + + if (FAILED(result)) + { + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + return false; + } + + if (removedDevice && lost) + { + ERR("Device lost reset failed multiple times"); + return false; + } + + // If the device was removed, we already finished re-initialization in resetRemovedDevice + if (!removedDevice) + { + // reset device defaults + initializeDevice(); + } + + return true; +} + +bool Renderer9::isRemovedDeviceResettable() const +{ + bool success = false; + +#if ANGLE_D3D9EX == ANGLE_ENABLED + IDirect3D9Ex *d3d9Ex = NULL; + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) + { + D3DCAPS9 deviceCaps; + HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); + success = SUCCEEDED(result); + } + + SafeRelease(d3d9Ex); +#else + ASSERT(UNREACHABLE()); +#endif + + return success; +} + +bool Renderer9::resetRemovedDevice() +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: + // The hardware adapter has been removed. Application must destroy the device, do enumeration of + // adapters and create another Direct3D device. If application continues rendering without + // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. + release(); + return !initialize().isError(); +} + +VendorID Renderer9::getVendorId() const +{ + return static_cast<VendorID>(mAdapterIdentifier.VendorId); +} + +std::string Renderer9::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mAdapterIdentifier.Description; + if (getShareHandleSupport()) + { + rendererString << " Direct3D9Ex"; + } + else + { + rendererString << " Direct3D9"; + } + + rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); + rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); + + return rendererString.str(); +} + +DeviceIdentifier Renderer9::getAdapterIdentifier() const +{ + DeviceIdentifier deviceIdentifier = { 0 }; + deviceIdentifier.VendorId = static_cast<UINT>(mAdapterIdentifier.VendorId); + deviceIdentifier.DeviceId = static_cast<UINT>(mAdapterIdentifier.DeviceId); + deviceIdentifier.SubSysId = static_cast<UINT>(mAdapterIdentifier.SubSysId); + deviceIdentifier.Revision = static_cast<UINT>(mAdapterIdentifier.Revision); + deviceIdentifier.FeatureLevel = 0; + + return deviceIdentifier; +} + +unsigned int Renderer9::getReservedVertexUniformVectors() const +{ + return d3d9_gl::GetReservedVertexUniformVectors(); +} + +unsigned int Renderer9::getReservedFragmentUniformVectors() const +{ + return d3d9_gl::GetReservedFragmentUniformVectors(); +} + +unsigned int Renderer9::getReservedVertexUniformBuffers() const +{ + return 0; +} + +unsigned int Renderer9::getReservedFragmentUniformBuffers() const +{ + return 0; +} + +bool Renderer9::getShareHandleSupport() const +{ + // PIX doesn't seem to support using share handles, so disable them. + return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive(); +} + +int Renderer9::getMajorShaderModel() const +{ + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); +} + +int Renderer9::getMinorShaderModel() const +{ + return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); +} + +std::string Renderer9::getShaderModelSuffix() const +{ + return ""; +} + +DWORD Renderer9::getCapsDeclTypes() const +{ + return mDeviceCaps.DeclTypes; +} + +D3DPOOL Renderer9::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level); +} + +gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level); +} + +gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + // 3D textures are not available in the D3D9 backend. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + // 2D array textures are not available in the D3D9 backend. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::copyTexture(const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::copyCompressedTexture(const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +{ + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); + + const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + IDirect3DTexture9 *texture = nullptr; + IDirect3DSurface9 *renderTarget = NULL; + if (width > 0 && height > 0) + { + bool requiresInitialization = false; + HRESULT result = D3DERR_INVALIDCALL; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, NULL); + } + else + { + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr); + if (supportedSamples > 0) + { + result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, nullptr); + } + else + { + result = mDevice->CreateTexture( + width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat, + getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr); + if (!FAILED(result)) + { + result = texture->GetSurfaceLevel(0, &renderTarget); + } + } + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == E_INVALIDARG); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result); + } + + if (requiresInitialization) + { + // This format requires that the data be initialized before the render target can be used + // Unfortunately this requires a Get call on the d3d device but it is far better than having + // to mark the render target as lockable and copy data to the gpu. + IDirect3DSurface9 *prevRenderTarget = NULL; + mDevice->GetRenderTarget(0, &prevRenderTarget); + mDevice->SetRenderTarget(0, renderTarget); + mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + mDevice->SetRenderTarget(0, prevRenderTarget); + } + } + + *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1, + supportedSamples); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) +{ + ASSERT(source != nullptr); + + RenderTargetD3D *newRT = nullptr; + gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), + source->getInternalFormat(), source->getSamples(), &newRT); + if (error.isError()) + { + return error; + } + + RenderTarget9 *source9 = GetAs<RenderTarget9>(source); + RenderTarget9 *dest9 = GetAs<RenderTarget9>(newRT); + + HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(), + nullptr, D3DTEXF_NONE); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy render target, result: 0x%X.", result); + } + + *outRT = newRT; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(streamOutVaryings.empty()); + + switch (type) + { + case SHADER_VERTEX: + { + IDirect3DVertexShader9 *vshader = NULL; + gl::Error error = createVertexShader((DWORD*)function, length, &vshader); + if (error.isError()) + { + return error; + } + *outExecutable = new ShaderExecutable9(function, length, vshader); + } + break; + case SHADER_PIXEL: + { + IDirect3DPixelShader9 *pshader = NULL; + gl::Error error = createPixelShader((DWORD*)function, length, &pshader); + if (error.isError()) + { + return error; + } + *outExecutable = new ShaderExecutable9(function, length, pshader); + } + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(streamOutVaryings.empty()); + + const char *profileType = NULL; + switch (type) + { + case SHADER_VERTEX: + profileType = "vs"; + break; + case SHADER_PIXEL: + profileType = "ps"; + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; + unsigned int profileMinorVersion = 0; + std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); + + UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; + + if (workarounds.skipOptimization) + { + flags = D3DCOMPILE_SKIP_OPTIMIZATION; + } + else if (workarounds.useMaxOptimization) + { + flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; + } + + if (gl::DebugAnnotationsActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + std::vector<CompileConfig> configs; + configs.push_back(CompileConfig(flags, "default" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control")); + + ID3DBlob *binary = NULL; + std::string debugInfo; + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo); + if (error.isError()) + { + return error; + } + + // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL + // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } + + error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + streamOutVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::Error(GL_NO_ERROR); +} + +UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize) +{ + return new UniformStorageD3D(storageSize); +} + +gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + return mBlit->boxFilter(source, dest); +} + +D3DPOOL Renderer9::getTexturePool(DWORD usage) const +{ + // Always use DEFAULT pool for textures, as there is a bug + // on XP (non-D3D9Ex) where we select MANAGED here, + // but trigger a crash in Image9::copyToSurface where the + // source pool is SYSTEMMEM, but the destination pool is + // MANAGED. It expects the dest pool to be DEFAULT + // if the source is SYSTEMMEM. + return D3DPOOL_DEFAULT; +} + +gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +{ + ASSERT(source && dest); + + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + + if (fromManaged) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + Image9::copyLockableSurfaces(surf, source); + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + SafeRelease(surf); + } + } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +ImageD3D *Renderer9::createImage() +{ + return new Image9(this); +} + +gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src) +{ + Image9 *src9 = GetAs<Image9>(src); + Image9 *dst9 = GetAs<Image9>(dest); + return Image9::generateMipmap(dst9, src9); +} + +gl::Error Renderer9::generateMipmapUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) +{ + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) +{ + SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain); + return new TextureStorage9_2D(this, swapChain9); +} + +TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) +{ + return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D)); +} + +TextureStorage *Renderer9::createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + UNIMPLEMENTED(); + return nullptr; +} + +TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); +} + +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); +} + +TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 3D textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + return false; +} + +VertexConversionType Renderer9::getVertexConversionType(gl::VertexFormatType vertexFormatType) const +{ + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).conversionType; +} + +GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType) const +{ + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType; +} + +gl::ErrorOrResult<unsigned int> Renderer9::getVertexSpaceRequired(const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const +{ + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = + d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType); + + if (!attrib.enabled) + { + return 16u; + } + + unsigned int elementCount = 0; + if (instances == 0 || attrib.divisor == 0) + { + elementCount = static_cast<unsigned int>(count); + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor); + } + + if (d3d9VertexInfo.outputElementSize > std::numeric_limits<unsigned int>::max() / elementCount) + { + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); + } + + return static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount; +} + +void Renderer9::generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const +{ + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, + outExtensions, outLimitations); +} + +WorkaroundsD3D Renderer9::generateWorkarounds() const +{ + return d3d9::GenerateWorkarounds(); +} + +gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +{ + // TODO(jmadill): faster way? + for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++) + { + gl::Error error = setTexture(samplerType, static_cast<int>(samplerIndex), nullptr); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +egl::Error Renderer9::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) + { + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice), + EGL_D3D9_DEVICE_ANGLE, EGL_FALSE); + + if (error.isError()) + { + SafeDelete(mEGLDevice); + return error; + } + } + + *device = static_cast<DeviceImpl *>(mEGLDevice); + return egl::Error(EGL_SUCCESS); +} + +Renderer9::CurSamplerState::CurSamplerState() + : forceSet(true), + baseLevel(std::numeric_limits<size_t>::max()), + samplerState() +{ +} + +gl::Error Renderer9::genericDrawElements(Context9 *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + const auto &data = context->getContextState(); + gl::Program *program = context->getGLState().getProgram(); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + bool usesPointSize = programD3D->usesPointSize(); + + programD3D->updateSamplerMapping(); + + if (!applyPrimitiveType(mode, count, usesPointSize)) + { + return gl::NoError(); + } + + ANGLE_TRY(updateState(context, mode)); + + TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; + + ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo)); + + applyTransformFeedbackBuffers(data.getState()); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the + // API validation + // layer. + ASSERT(!data.getState().isTransformFeedbackActiveUnpaused()); + + size_t vertexCount = indexInfo.indexRange.vertexCount(); + ANGLE_TRY(applyVertexBuffer(data.getState(), mode, + static_cast<GLsizei>(indexInfo.indexRange.start), + static_cast<GLsizei>(vertexCount), instances, &indexInfo)); + ANGLE_TRY(applyTextures(context, data)); + ANGLE_TRY(applyShaders(data, mode)); + ANGLE_TRY(programD3D->applyUniformBuffers(data)); + + if (!skipDraw(data, mode)) + { + ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances)); + } + + return gl::NoError(); +} + +gl::Error Renderer9::genericDrawArrays(Context9 *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances) +{ + const auto &data = context->getContextState(); + gl::Program *program = context->getGLState().getProgram(); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + bool usesPointSize = programD3D->usesPointSize(); + + programD3D->updateSamplerMapping(); + + if (!applyPrimitiveType(mode, count, usesPointSize)) + { + return gl::NoError(); + } + + ANGLE_TRY(updateState(context, mode)); + ANGLE_TRY(applyTransformFeedbackBuffers(data.getState())); + ANGLE_TRY(applyVertexBuffer(data.getState(), mode, first, count, instances, nullptr)); + ANGLE_TRY(applyTextures(context, data)); + ANGLE_TRY(applyShaders(data, mode)); + ANGLE_TRY(programD3D->applyUniformBuffers(data)); + + if (!skipDraw(data, mode)) + { + ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances)); + + if (data.getState().isTransformFeedbackActiveUnpaused()) + { + ANGLE_TRY(markTransformFeedbackUsage(data)); + } + } + + return gl::NoError(); +} + +FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + return new Framebuffer9(state, this); +} + +gl::Version Renderer9::getMaxSupportedESVersion() const +{ + return gl::Version(2, 0); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h new file mode 100755 index 000000000..9c3ae8b04 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -0,0 +1,487 @@ +// +// 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. +// + +// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h" +#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" +#include "libANGLE/renderer/driver_utils.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace egl +{ +class AttributeMap; +} + +namespace rx +{ +class Blit9; +class Context9; +class IndexDataManager; +class ProgramD3D; +class StreamingIndexBufferInterface; +class StaticIndexBufferInterface; +class VertexDataManager; +struct ClearParameters; +struct D3DUniform; +struct TranslatedAttribute; + +enum D3D9InitError +{ + D3D9_INIT_SUCCESS = 0, + // Failed to load the D3D or ANGLE compiler + D3D9_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL + D3D9_INIT_MISSING_DEP, + // Device creation error + D3D9_INIT_CREATE_DEVICE_ERROR, + // System does not meet minimum shader spec + D3D9_INIT_UNSUPPORTED_VERSION, + // System does not support stretchrect from textures + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + // A call returned out of memory or device lost + D3D9_INIT_OUT_OF_MEMORY, + // Other unspecified error + D3D9_INIT_OTHER_ERROR, + NUM_D3D9_INIT_ERRORS +}; + +class Renderer9 : public RendererD3D +{ + public: + explicit Renderer9(egl::Display *display); + virtual ~Renderer9(); + + egl::Error initialize() override; + bool resetDevice() override; + + egl::ConfigSet generateConfigs() override; + void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; + + void startScene(); + void endScene(); + + gl::Error flush(); + gl::Error finish(); + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const override; + + SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; + egl::Error getD3DTextureInfo(IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const override; + egl::Error validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const override; + + ContextImpl *createContext(const gl::ContextState &state) override; + + gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); + void freeEventQuery(IDirect3DQuery9* query); + + // resource creation + gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader); + gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader); + HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); + HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); + gl::Error setSamplerState(gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &sampler) override; + gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override; + + gl::Error setUniformBuffers(const gl::ContextState &data, + const std::vector<GLint> &vertexUniformBuffers, + const std::vector<GLint> &fragmentUniformBuffers) override; + + gl::Error updateState(Context9 *context, GLenum drawMode); + + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + void setViewport(const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport); + + gl::Error applyRenderTarget(GLImplFactory *implFactory, const gl::Framebuffer *frameBuffer); + gl::Error applyRenderTarget(GLImplFactory *implFactory, + const gl::FramebufferAttachment *colorAttachment, + const gl::FramebufferAttachment *depthStencilAttachment); + gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector<D3DUniform *> &uniformArray) override; + bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); + gl::Error applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo); + gl::Error applyIndexBuffer(const gl::ContextState &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo); + + gl::Error applyTransformFeedbackBuffers(const gl::State &state); + + gl::Error clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer); + + void markAllStateDirty(); + + // lost device + bool testDeviceLost() override; + bool testDeviceResettable(); + + VendorID getVendorId() const; + std::string getRendererDescription() const; + DeviceIdentifier getAdapterIdentifier() const override; + + IDirect3DDevice9 *getDevice() { return mDevice; } + void *getD3DDevice() override; + + unsigned int getReservedVertexUniformVectors() const; + unsigned int getReservedFragmentUniformVectors() const; + unsigned int getReservedVertexUniformBuffers() const override; + unsigned int getReservedFragmentUniformBuffers() const override; + + bool getShareHandleSupport() const; + + int getMajorShaderModel() const override; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; + + DWORD getCapsDeclTypes() const; + + // Pixel operations + gl::Error copyImage2D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImageCube(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level) override; + gl::Error copyImage3D(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + + gl::Error copyTexture(const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + gl::Error copyCompressedTexture(const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) override; + + // RenderTarget creation + gl::Error createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) override; + gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; + + // Shader operations + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; + + // Image operations + ImageD3D *createImage() override; + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) override; + TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override; + TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) override; + TextureStorage *createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + TextureStorage *createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + TextureStorage *createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + + // Buffer creation + VertexBuffer *createVertexBuffer() override; + IndexBuffer *createIndexBuffer() override; + + // Stream Creation + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; + + // Buffer-to-texture and Texture-to-buffer copies + bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override; + gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) override; + + // D3D9-renderer specific methods + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + D3DPOOL getTexturePool(DWORD usage) const; + + bool getLUID(LUID *adapterLuid) const override; + VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; + gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib, + GLsizei count, + GLsizei instances) const override; + + gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + + RendererClass getRendererClass() const override { return RENDERER_D3D9; } + + D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; } + + egl::Error getEGLDevice(DeviceImpl **device) override; + + StateManager9 *getStateManager() { return &mStateManager; } + + gl::Error genericDrawArrays(Context9 *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances); + + gl::Error genericDrawElements(Context9 *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange); + + // Necessary hack for default framebuffers in D3D. + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + DebugAnnotator9 *getAnnotator() { return &mAnnotator; } + + gl::Version getMaxSupportedESVersion() const override; + + protected: + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; + + private: + gl::Error drawArraysImpl(const gl::ContextState &data, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances); + gl::Error drawElementsImpl(const gl::ContextState &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances); + + gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode); + + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const override; + + WorkaroundsD3D generateWorkarounds() const override; + + gl::Error setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode); + + void release(); + + void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v); + void applyUniformniv(const D3DUniform *targetUniform, const GLint *v); + void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v); + + gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + + gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); + + gl::Error getNullColorbuffer(GLImplFactory *implFactory, + const gl::FramebufferAttachment *depthbuffer, + const gl::FramebufferAttachment **outColorBuffer); + + D3DPOOL getBufferPool(DWORD usage) const; + + HMODULE mD3d9Module; + + void initializeDevice(); + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + void releaseDeviceResources(); + + HRESULT getDeviceStatusCode(); + bool isRemovedDeviceResettable() const; + bool resetRemovedDevice(); + + UINT mAdapter; + D3DDEVTYPE mDeviceType; + IDirect3D9 *mD3d9; // Always valid after successful initialization. + IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. + IDirect3DDevice9 *mDevice; + IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. + + HLSLCompiler mCompiler; + + Blit9 *mBlit; + + HWND mDeviceWindow; + + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + + D3DPRIMITIVETYPE mPrimitiveType; + int mPrimitiveCount; + GLsizei mRepeatDraw; + + bool mSceneStarted; + + bool mVertexTextureSupport; + + // current render target states + unsigned int mAppliedRenderTargetSerial; + unsigned int mAppliedDepthStencilSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + StateManager9 mStateManager; + + // Currently applied sampler states + struct CurSamplerState + { + CurSamplerState(); + + bool forceSet; + size_t baseLevel; + gl::SamplerState samplerState; + }; + std::vector<CurSamplerState> mCurVertexSamplerStates; + std::vector<CurSamplerState> mCurPixelSamplerStates; + + // Currently applied textures + std::vector<uintptr_t> mCurVertexTextures; + std::vector<uintptr_t> mCurPixelTextures; + + unsigned int mAppliedIBSerial; + IDirect3DVertexShader9 *mAppliedVertexShader; + IDirect3DPixelShader9 *mAppliedPixelShader; + unsigned int mAppliedProgramSerial; + + // A pool of event queries that are currently unused. + std::vector<IDirect3DQuery9*> mEventQueryPool; + VertexShaderCache mVertexShaderCache; + PixelShaderCache mPixelShaderCache; + + VertexDataManager *mVertexDataManager; + VertexDeclarationCache mVertexDeclarationCache; + + IndexDataManager *mIndexDataManager; + StreamingIndexBufferInterface *mLineLoopIB; + StaticIndexBufferInterface *mCountingIB; + + enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + struct NullColorbufferCacheEntry + { + UINT lruCount; + int width; + int height; + gl::FramebufferAttachment *buffer; + } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; + UINT mMaxNullColorbufferLRU; + + DeviceD3D *mEGLDevice; + std::vector<TranslatedAttribute> mTranslatedAttribCache; + + DebugAnnotator9 mAnnotator; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h new file mode 100755 index 000000000..cf831c62f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2012 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. +// + +// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects +// keyed by their byte code. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ + +#include "libANGLE/Error.h" + +#include "common/debug.h" + +#include <cstddef> +#include <unordered_map> +#include <string> + +namespace rx +{ +template <typename ShaderObject> +class ShaderCache : angle::NonCopyable +{ + public: + ShaderCache() : mDevice(NULL) + { + } + + ~ShaderCache() + { + // Call clear while the device is still valid. + ASSERT(mMap.empty()); + } + + void initialize(IDirect3DDevice9* device) + { + mDevice = device; + } + + gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject) + { + std::string key(reinterpret_cast<const char*>(function), length); + typename Map::iterator it = mMap.find(key); + if (it != mMap.end()) + { + it->second->AddRef(); + *outShaderObject = it->second; + return gl::Error(GL_NO_ERROR); + } + + ShaderObject *shader; + HRESULT result = createShader(function, &shader); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result); + } + + // Random eviction policy. + if (mMap.size() >= kMaxMapSize) + { + SafeRelease(mMap.begin()->second); + mMap.erase(mMap.begin()); + } + + shader->AddRef(); + mMap[key] = shader; + + *outShaderObject = shader; + return gl::Error(GL_NO_ERROR); + } + + void clear() + { + for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) + { + SafeRelease(it->second); + } + + mMap.clear(); + } + + private: + const static size_t kMaxMapSize = 100; + + HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) + { + return mDevice->CreateVertexShader(function, shader); + } + + HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) + { + return mDevice->CreatePixelShader(function, shader); + } + + typedef std::unordered_map<std::string, ShaderObject*> Map; + Map mMap; + + IDirect3DDevice9 *mDevice; +}; + +typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache; +typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp new file mode 100755 index 000000000..dcce8fd2f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -0,0 +1,47 @@ +// +// Copyright (c) 2012-2013 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. +// + +// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader +// executable implementation details. + +#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) + : ShaderExecutableD3D(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; +} + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) + : ShaderExecutableD3D(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; +} + +ShaderExecutable9::~ShaderExecutable9() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); +} + +IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const +{ + return mVertexExecutable; +} + +IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const +{ + return mPixelExecutable; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h new file mode 100755 index 000000000..382a68c82 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2012-2013 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. +// + +// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader +// executable implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +namespace rx +{ + +class ShaderExecutable9 : public ShaderExecutableD3D +{ + public: + ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); + ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); + virtual ~ShaderExecutable9(); + + IDirect3DPixelShader9 *getPixelShader() const; + IDirect3DVertexShader9 *getVertexShader() const; + + private: + IDirect3DPixelShader9 *mPixelExecutable; + IDirect3DVertexShader9 *mVertexExecutable; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp new file mode 100755 index 000000000..54885bf81 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp @@ -0,0 +1,945 @@ +// +// 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. +// + +// StateManager9.cpp: Defines a class for caching D3D9 state +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +StateManager9::StateManager9(Renderer9 *renderer9) + : mUsingZeroColorMaskWorkaround(false), + mCurBlendState(), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mCurRasterState(), + mCurDepthSize(0), + mCurDepthStencilState(), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurFrontFaceCCW(0), + mCurStencilSize(0), + mCurScissorRect(), + mCurScissorEnabled(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mCurDepthFront(0.0f), + mCurIgnoreViewport(false), + mRenderer9(renderer9), + mDirtyBits() +{ + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK); + mBlendStateDirtyBits.set(DIRTY_BIT_DITHER); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK); + + mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE); + mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); +} + +StateManager9::~StateManager9() +{ +} + +void StateManager9::initialize() +{ + mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId()); +} + +void StateManager9::forceSetBlendState() +{ + mDirtyBits |= mBlendStateDirtyBits; +} + +void StateManager9::forceSetRasterState() +{ + mDirtyBits |= mRasterizerStateDirtyBits; +} + +void StateManager9::forceSetDepthStencilState() +{ + mDirtyBits |= mDepthStencilStateDirtyBits; +} + +void StateManager9::forceSetScissorState() +{ + mDirtyBits |= mScissorStateDirtyBits; +} + +void StateManager9::forceSetViewportState() +{ + mForceSetViewport = true; +} + +void StateManager9::forceSetDXUniformsState() +{ + mDxUniformsDirty = true; +} + +void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + forceSetDepthStencilState(); + } +} + +void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + if (!dirtyBits.any()) + { + return; + } + + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + // BlendColor and funcs and equations has to be set if blend is enabled + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + + // The color mask may have to be updated if the blend state changes + if (mUsingZeroColorMaskWorkaround) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + } + } + 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) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + // BlendColor depends on the values of blend funcs + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + + // The color mask may have to be updated if the blend funcs change + if (mUsingZeroColorMaskWorkaround) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + } + } + break; + } + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || + blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + + // The color mask may have to be updated if the blend funcs change + if (mUsingZeroColorMaskWorkaround) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + } + } + break; + } + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + } + 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) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + + // The color mask can cause the blend state to get out of sync when using the + // zero color mask workaround + if (mUsingZeroColorMaskWorkaround) + { + mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + } + } + break; + } + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mDirtyBits.set(DIRTY_BIT_DITHER); + } + break; + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + + // Viewport state depends on rasterizer.frontface + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterizerState = state.getRasterizerState(); + if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + } + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + // If we enable the stencil test, all of these must be set + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc || + depthStencilState.stencilMask != mCurDepthStencilState.stencilMask || + state.getStencilRef() != mCurStencilRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || + depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask || + state.getStencilBackRef() != mCurStencilBackRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail || + depthStencilState.stencilPassDepthFail != + mCurDepthStencilState.stencilPassDepthFail || + depthStencilState.stencilPassDepthPass != + mCurDepthStencilState.stencilPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail || + depthStencilState.stencilBackPassDepthFail != + mCurDepthStencilState.stencilBackPassDepthFail || + depthStencilState.stencilBackPassDepthPass != + mCurDepthStencilState.stencilBackPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + // If scissor is enabled, we have to set the scissor rect + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + default: + break; + } + } +} + +gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, + unsigned int sampleMask) +{ + const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + + const gl::BlendState &blendState = glState.getBlendState(); + const gl::ColorF &blendColor = glState.getBlendColor(); + const gl::RasterizerState &rasterState = glState.getRasterizerState(); + + const auto &depthStencilState = glState.getDepthStencilState(); + bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW); + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + // All the depth stencil states depends on the front face ccw variable + if (frontFaceCCW != mCurFrontFaceCCW) + { + forceSetDepthStencilState(); + mCurFrontFaceCCW = frontFaceCCW; + } + + for (auto dirtyBit : angle::IterateBitSet(mDirtyBits)) + { + switch (dirtyBit) + { + case DIRTY_BIT_BLEND_ENABLED: + setBlendEnabled(blendState.blend); + break; + case DIRTY_BIT_BLEND_COLOR: + setBlendColor(blendState, blendColor); + break; + case DIRTY_BIT_BLEND_FUNCS_EQUATIONS: + setBlendFuncsEquations(blendState); + break; + case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE: + setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage); + break; + case DIRTY_BIT_COLOR_MASK: + setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue, + blendState.colorMaskGreen, blendState.colorMaskAlpha); + break; + case DIRTY_BIT_DITHER: + setDither(blendState.dither); + break; + case DIRTY_BIT_CULL_MODE: + setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace); + break; + case DIRTY_BIT_DEPTH_BIAS: + setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor, + rasterState.polygonOffsetUnits); + break; + case DIRTY_BIT_STENCIL_DEPTH_MASK: + setDepthMask(depthStencilState.depthMask); + break; + case DIRTY_BIT_STENCIL_DEPTH_FUNC: + setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc); + break; + case DIRTY_BIT_STENCIL_TEST_ENABLED: + setStencilTestEnabled(depthStencilState.stencilTest); + break; + case DIRTY_BIT_STENCIL_FUNCS_FRONT: + setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask, + glState.getStencilRef(), frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_FUNCS_BACK: + setStencilFuncsBack(depthStencilState.stencilBackFunc, + depthStencilState.stencilBackMask, glState.getStencilBackRef(), + frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_BACK: + setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_FRONT: + setStencilOpsFront(depthStencilState.stencilFail, + depthStencilState.stencilPassDepthFail, + depthStencilState.stencilPassDepthPass, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_BACK: + setStencilOpsBack(depthStencilState.stencilBackFail, + depthStencilState.stencilBackPassDepthFail, + depthStencilState.stencilBackPassDepthPass, frontFaceCCW); + break; + default: + break; + } + } + + if (sampleMask != mCurSampleMask) + { + setSampleMask(sampleMask); + } + + return gl::Error(GL_NO_ERROR); +} + +void StateManager9::setViewportState(const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport) +{ + if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport) + return; + + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = static_cast<int>(mRenderTargetBounds.width); + actualViewport.height = static_cast<int>(mRenderTargetBounds.height); + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height)); + dxViewport.Width = + gl::clamp(actualViewport.width, 0, + static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X)); + dxViewport.Height = + gl::clamp(actualViewport.height, 0, + static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + mRenderer9->getDevice()->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + mCurIgnoreViewport = ignoreViewport; + + // Setting shader constants + dx_VertexConstants9 vc = {}; + dx_PixelConstants9 pc = {}; + + vc.viewAdjust[0] = + static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) + + 2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) / + dxViewport.Width; + vc.viewAdjust[1] = + static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) + + 2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) / + dxViewport.Height; + vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width; + vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + + mForceSetViewport = false; +} + +void StateManager9::setShaderConstants() +{ + if (!mDxUniformsDirty) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants), + sizeof(dx_VertexConstants9) / sizeof(float[4])); + device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants), + sizeof(dx_PixelConstants9) / sizeof(float[4])); + mDxUniformsDirty = false; +} + +// This is separate from the main state loop because other functions +// outside call only setScissorState to update scissor state +void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled) +{ + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED)) + setScissorEnabled(enabled); + + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT)) + setScissorRect(scissor, enabled); +} + +void StateManager9::setRenderTargetBounds(size_t width, size_t height) +{ + mRenderTargetBounds.width = (int)width; + mRenderTargetBounds.height = (int)height; + forceSetViewportState(); +} + +void StateManager9::setScissorEnabled(bool scissorEnabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE); + mCurScissorEnabled = scissorEnabled; +} + +void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled) +{ + if (!enabled) + return; + + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height)); + rect.right = + gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width)); + rect.bottom = + gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height)); + mRenderer9->getDevice()->SetScissorRect(&rect); +} + +void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc) +{ + if (depthTest) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState.depthTest = depthTest; + mCurDepthStencilState.depthFunc = depthFunc; +} + +void StateManager9::setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW) +{ + // TODO(dianx) It may be slightly more efficient todo these and other similar areas + // with separate dirty bits. + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilPassDepthFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilPassDepthPass)); + + mCurDepthStencilState.stencilFail = stencilFail; + mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail; + mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass; +} + +void StateManager9::setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilBackFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass)); + + mCurDepthStencilState.stencilBackFail = stencilBackFail; + mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail; + mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask); + + mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask; +} + +void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilBackFunc)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + stencilBackMask); + + mCurDepthStencilState.stencilBackFunc = stencilBackFunc; + mCurStencilBackRef = stencilBackRef; + mCurDepthStencilState.stencilBackMask = stencilBackMask; +} + +void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask); + mCurDepthStencilState.stencilWritemask = stencilWriteMask; +} + +void StateManager9::setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilFunc)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask); + + mCurDepthStencilState.stencilFunc = stencilFunc; + mCurStencilRef = stencilRef; + mCurDepthStencilState.stencilMask = stencilMask; +} +void StateManager9::setStencilTestEnabled(bool stencilTestEnabled) +{ + if (stencilTestEnabled && mCurStencilSize > 0) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mCurDepthStencilState.stencilTest = stencilTestEnabled; +} + +void StateManager9::setDepthMask(bool depthMask) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE); + mCurDepthStencilState.depthMask = depthMask; +} + +// TODO(dianx) one bit for sampleAlphaToCoverage +void StateManager9::setSampleAlphaToCoverage(bool enabled) +{ + if (enabled) + { + FIXME("Sample alpha to coverage is unimplemented."); + } +} + +void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor) +{ + if (!blendState.blend) + return; + + 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) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR, + gl_d3d9::ConvertColor(blendColor)); + } + else + { + mRenderer9->getDevice()->SetRenderState( + D3DRS_BLENDFACTOR, + D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha))); + } + mCurBlendColor = blendColor; +} + +void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState) +{ + if (!blendState.blend) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + + device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + device->SetRenderState(D3DRS_DESTBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + device->SetRenderState(D3DRS_BLENDOPALPHA, + gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + + mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB; + mCurBlendState.destBlendRGB = blendState.destBlendRGB; + mCurBlendState.blendEquationRGB = blendState.blendEquationRGB; + mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha; +} + +void StateManager9::setBlendEnabled(bool enabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE); + mCurBlendState.blend = enabled; +} + +void StateManager9::setDither(bool dither) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE); + mCurBlendState.dither = dither; +} + +// TODO(dianx) one bit for color mask +void StateManager9::setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha) +{ + // Set the color mask + + const auto *attachment = framebuffer->getFirstColorbuffer(); + const auto &format = attachment ? attachment->getFormat() : gl::Format::Invalid(); + + DWORD colorMask = gl_d3d9::ConvertColorMask( + format.info->redBits > 0 && red, format.info->greenBits > 0 && green, + format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha); + + // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause + // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the + // blend state so that no drawing is done. + // http://anglebug.com/169 + if (colorMask == 0 && mUsingZeroColorMaskWorkaround) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + // Enable green channel, but set blending so nothing will be drawn. + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + + device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + + mCurBlendState.colorMaskRed = false; + mCurBlendState.colorMaskGreen = true; + mCurBlendState.colorMaskBlue = false; + mCurBlendState.colorMaskAlpha = false; + + mCurBlendState.blend = true; + mCurBlendState.sourceBlendRGB = GL_ZERO; + mCurBlendState.sourceBlendAlpha = GL_ZERO; + mCurBlendState.destBlendRGB = GL_ONE; + mCurBlendState.destBlendAlpha = GL_ONE; + mCurBlendState.blendEquationRGB = GL_FUNC_ADD; + mCurBlendState.blendEquationAlpha = GL_FUNC_ADD; + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + + mCurBlendState.colorMaskRed = red; + mCurBlendState.colorMaskGreen = green; + mCurBlendState.colorMaskBlue = blue; + mCurBlendState.colorMaskAlpha = alpha; + } +} + +void StateManager9::setSampleMask(unsigned int sampleMask) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + // Set the multisample mask + device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); + + mCurSampleMask = sampleMask; +} + +void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace) +{ + if (cullFace) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, + gl_d3d9::ConvertCullMode(cullMode, frontFace)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + mCurRasterState.cullFace = cullFace; + mCurRasterState.cullMode = cullMode; + mCurRasterState.frontFace = frontFace; +} + +void StateManager9::setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits) +{ + if (polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor); + + float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); + device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias); + } + } + else + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + device->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState.polygonOffsetFill = polygonOffsetFill; + mCurRasterState.polygonOffsetFactor = polygonOffsetFactor; + mCurRasterState.polygonOffsetUnits = polygonOffsetUnits; +} + +void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize) +{ + if (!depthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + forceSetRasterState(); + } +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h new file mode 100755 index 000000000..bd2cef2e5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h @@ -0,0 +1,209 @@ +// +// 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. +// + +// StateManager9.h: Defines a class for caching D3D9 state + +#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ +#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +class Renderer9; + +struct dx_VertexConstants9 +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; +}; + +struct dx_PixelConstants9 +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; +}; + +class StateManager9 final : angle::NonCopyable +{ + public: + StateManager9(Renderer9 *renderer9); + ~StateManager9(); + + void initialize(); + + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + + gl::Error setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask); + void setScissorState(const gl::Rectangle &scissor, bool enabled); + void setViewportState(const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport); + + void setShaderConstants(); + + void forceSetBlendState(); + void forceSetRasterState(); + void forceSetDepthStencilState(); + void forceSetScissorState(); + void forceSetViewportState(); + void forceSetDXUniformsState(); + + void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize); + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + void setRenderTargetBounds(size_t width, size_t height); + + int getRenderTargetWidth() const { return mRenderTargetBounds.width; } + int getRenderTargetHeight() const { return mRenderTargetBounds.height; } + + void resetDirtyBits() { mDirtyBits.reset(); } + + private: + // Blend state functions + void setBlendEnabled(bool enabled); + void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor); + void setBlendFuncsEquations(const gl::BlendState &blendState); + void setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha); + void setSampleAlphaToCoverage(bool enabled); + void setDither(bool dither); + void setSampleMask(unsigned int sampleMask); + + // Current raster state functions + void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace); + void setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits); + + // Depth stencil state functions + void setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW); + void setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW); + void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW); + void setDepthFunc(bool depthTest, GLenum depthFunc); + void setStencilTestEnabled(bool enabled); + void setDepthMask(bool depthMask); + void setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW); + + void setScissorEnabled(bool scissorEnabled); + void setScissorRect(const gl::Rectangle &scissor, bool enabled); + + enum DirtyBitType + { + // Blend dirty bits + DIRTY_BIT_BLEND_ENABLED, + DIRTY_BIT_BLEND_COLOR, + DIRTY_BIT_BLEND_FUNCS_EQUATIONS, + DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE, + DIRTY_BIT_COLOR_MASK, + DIRTY_BIT_DITHER, + DIRTY_BIT_SAMPLE_MASK, + + // Rasterizer dirty bits + DIRTY_BIT_CULL_MODE, + DIRTY_BIT_DEPTH_BIAS, + + // Depth stencil dirty bits + DIRTY_BIT_STENCIL_DEPTH_MASK, + DIRTY_BIT_STENCIL_DEPTH_FUNC, + DIRTY_BIT_STENCIL_TEST_ENABLED, + DIRTY_BIT_STENCIL_FUNCS_FRONT, + DIRTY_BIT_STENCIL_FUNCS_BACK, + DIRTY_BIT_STENCIL_WRITEMASK_FRONT, + DIRTY_BIT_STENCIL_WRITEMASK_BACK, + DIRTY_BIT_STENCIL_OPS_FRONT, + DIRTY_BIT_STENCIL_OPS_BACK, + + // Scissor dirty bits + DIRTY_BIT_SCISSOR_ENABLED, + DIRTY_BIT_SCISSOR_RECT, + + // Viewport dirty bits + DIRTY_BIT_VIEWPORT, + + DIRTY_BIT_MAX + }; + + typedef std::bitset<DIRTY_BIT_MAX> DirtyBits; + + bool mUsingZeroColorMaskWorkaround; + + // Currently applied blend state + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + DirtyBits mBlendStateDirtyBits; + + // Currently applied raster state + gl::RasterizerState mCurRasterState; + unsigned int mCurDepthSize; + DirtyBits mRasterizerStateDirtyBits; + + // Currently applied depth stencil state + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + unsigned int mCurStencilSize; + DirtyBits mDepthStencilStateDirtyBits; + + // Currently applied scissor states + gl::Rectangle mCurScissorRect; + bool mCurScissorEnabled; + gl::Extents mRenderTargetBounds; + DirtyBits mScissorStateDirtyBits; + + // Currently applied viewport states + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + bool mCurIgnoreViewport; + + dx_VertexConstants9 mVertexConstants; + dx_PixelConstants9 mPixelConstants; + bool mDxUniformsDirty; + + // FIXME: Unsupported by D3D9 + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + + Renderer9 *mRenderer9; + DirtyBits mDirtyBits; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp new file mode 100755 index 000000000..7e6948ebb --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -0,0 +1,442 @@ +// +// 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. +// + +// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. + +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/features.h" + +namespace rx +{ + +SwapChain9::SwapChain9(Renderer9 *renderer, + NativeWindow9 *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) + : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat), + mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mSwapInterval(-1), + mNativeWindow(nativeWindow), + mSwapChain(nullptr), + mBackBuffer(nullptr), + mRenderTarget(nullptr), + mDepthStencil(nullptr), + mOffscreenTexture(nullptr), + mColorRenderTarget(this, false), + mDepthStencilRenderTarget(this, true) +{ + ASSERT(orientation == 0); +} + +SwapChain9::~SwapChain9() +{ + release(); +} + +void SwapChain9::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mDepthStencil); + SafeRelease(mRenderTarget); + SafeRelease(mOffscreenTexture); + + if (mNativeWindow->getNativeWindow()) + { + mShareHandle = NULL; + } +} + +static DWORD convertInterval(EGLint interval) +{ +#if ANGLE_VSYNC == ANGLE_DISABLED + return D3DPRESENT_INTERVAL_IMMEDIATE; +#else + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +#endif +} + +EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +{ + // D3D9 does not support resizing swap chains without recreating them + return reset(backbufferWidth, backbufferHeight, mSwapInterval); +} + +EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + + HRESULT result; + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mOffscreenTexture); + SafeRelease(mDepthStencil); + + const d3d9::TextureFormat &backBufferd3dFormatInfo = + d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat); + if (mD3DTexture != nullptr) + { + result = mD3DTexture->QueryInterface(&mOffscreenTexture); + ASSERT(SUCCEEDED(result)); + } + else + { + HANDLE *pShareHandle = NULL; + if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport()) + { + pShareHandle = &mShareHandle; + } + + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, + &mOffscreenTexture, pShareHandle); + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + IDirect3DSurface9 *oldRenderTarget = mRenderTarget; + + result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); + ASSERT(SUCCEEDED(result)); + + if (oldRenderTarget) + { + RECT rect = + { + 0, 0, + mWidth, mHeight + }; + + if (rect.right > static_cast<LONG>(backbufferWidth)) + { + rect.right = backbufferWidth; + } + + if (rect.bottom > static_cast<LONG>(backbufferHeight)) + { + rect.bottom = backbufferHeight; + } + + mRenderer->endScene(); + + result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); + ASSERT(SUCCEEDED(result)); + + SafeRelease(oldRenderTarget); + } + + const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); + + // Don't create a swapchain for NULLREF devices + D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType(); + EGLNativeWindowType window = mNativeWindow->getNativeWindow(); + if (window && deviceType != D3DDEVTYPE_NULLREF) + { + D3DPRESENT_PARAMETERS presentParameters = {0}; + presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = window; + presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented + presentParameters.PresentationInterval = convertInterval(swapInterval); + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; + + // http://crbug.com/140239 + // http://crbug.com/143434 + // + // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width + // when using the integrated Intel. This rounds the width up rather than down. + // + // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID + // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. + if (IsIntel(mRenderer->getVendorId())) + { + presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; + } + + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); + + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); + InvalidateRect(window, NULL, FALSE); + } + + if (mDepthBufferFormat != GL_NONE) + { + result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, + depthBufferd3dFormatInfo.renderFormat, + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapInterval = swapInterval; + + return EGL_SUCCESS; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + // Disable all pipeline operations + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + + device->SetRenderTarget(0, mBackBuffer); + device->SetDepthStencilSurface(NULL); + + device->SetTexture(0, mOffscreenTexture); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) + { + device->SetStreamSourceFreq(streamIndex, 1); + } + + D3DVIEWPORT9 viewport = {0, 0, static_cast<DWORD>(mWidth), static_cast<DWORD>(mHeight), 0.0f, 1.0f}; + device->SetViewport(&viewport); + + float x1 = x - 0.5f; + float y1 = (mHeight - y - height) - 0.5f; + float x2 = (x + width) - 0.5f; + float y2 = (mHeight - y) - 0.5f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, + {x2, y1, 0.0f, 1.0f, u2, v2}, + {x2, y2, 0.0f, 1.0f, u2, v1}, + {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v + + mRenderer->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); + mRenderer->endScene(); + + device->SetTexture(0, NULL); + + RECT rect = + { + static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), + static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y) + }; + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + + mRenderer->markAllStateDirty(); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return EGL_BAD_ALLOC; + } + + // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is + // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The + // device appears to be ok after emitting this error so simply return a failure to swap. + if (result == static_cast<HRESULT>(0x88760873)) + { + return EGL_BAD_MATCH; + } + + // http://crbug.com/313210 + // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific + // device removed bug with lost contexts when reinstalling drivers. + if (FAILED(result)) + { + mRenderer->notifyDeviceLost(); + return EGL_CONTEXT_LOST; + } + + return EGL_SUCCESS; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getRenderTarget() +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getDepthStencil() +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +// TODO: remove the AddRef to match SwapChain11 +IDirect3DTexture9 *SwapChain9::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +void *SwapChain9::getKeyedMutex() +{ + UNREACHABLE(); + return nullptr; +} + +void SwapChain9::recreate() +{ + if (!mSwapChain) + { + return; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + if (device == NULL) + { + return; + } + + D3DPRESENT_PARAMETERS presentParameters; + HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); + ASSERT(SUCCEEDED(result)); + + IDirect3DSwapChain9* newSwapChain = NULL; + result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); + if (FAILED(result)) + { + return; + } + + SafeRelease(mSwapChain); + mSwapChain = newSwapChain; + + SafeRelease(mBackBuffer); + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h new file mode 100755 index 000000000..2e5cce1db --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2012 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. +// + +// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ + +#include "common/angleutils.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" + +namespace rx +{ +class NativeWindow9; +class Renderer9; + +class SwapChain9 : public SwapChainD3D +{ + public: + SwapChain9(Renderer9 *renderer, + NativeWindow9 *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); + virtual ~SwapChain9(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual void recreate(); + + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + void *getKeyedMutex() override; + + private: + void release(); + + Renderer9 *mRenderer; + EGLint mWidth; + EGLint mHeight; + EGLint mSwapInterval; + + NativeWindow9 *mNativeWindow; + + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mBackBuffer; + IDirect3DSurface9 *mRenderTarget; + IDirect3DSurface9 *mDepthStencil; + IDirect3DTexture9* mOffscreenTexture; + + SurfaceRenderTarget9 mColorRenderTarget; + SurfaceRenderTarget9 mDepthStencilRenderTarget; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp new file mode 100755 index 000000000..db8765218 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -0,0 +1,617 @@ +// +// 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. +// + +// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" + +namespace rx +{ +TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) + : mTopLevel(0), + mMipLevels(0), + mTextureWidth(0), + mTextureHeight(0), + mInternalFormat(GL_NONE), + mTextureFormat(D3DFMT_UNKNOWN), + mRenderer(renderer), + mD3DUsage(usage), + mD3DPool(mRenderer->getTexturePool(usage)) +{ +} + +TextureStorage9::~TextureStorage9() +{ +} + +DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) +{ + DWORD d3dusage = 0; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + d3dusage |= D3DUSAGE_DEPTHSTENCIL; + } + else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)) + { + d3dusage |= D3DUSAGE_RENDERTARGET; + } + + return d3dusage; +} + + +bool TextureStorage9::isRenderTarget() const +{ + return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; +} + +bool TextureStorage9::isManaged() const +{ + return (mD3DPool == D3DPOOL_MANAGED); +} + +bool TextureStorage9::supportsNativeMipmapFunction() const +{ + return false; +} + +D3DPOOL TextureStorage9::getPool() const +{ + return mD3DPool; +} + +DWORD TextureStorage9::getUsage() const +{ + return mD3DUsage; +} + +int TextureStorage9::getTopLevel() const +{ + return mTopLevel; +} + +int TextureStorage9::getLevelCount() const +{ + return static_cast<int>(mMipLevels) - mTopLevel; +} + +gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +{ + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); + mTexture = surfaceTexture; + mMipLevels = surfaceTexture->GetLevelCount(); + + mInternalFormat = swapchain->getRenderTargetInternalFormat(); + + D3DSURFACE_DESC surfaceDesc; + surfaceTexture->GetLevelDesc(0, &surfaceDesc); + mTextureWidth = surfaceDesc.Width; + mTextureHeight = surfaceDesc.Height; + mTextureFormat = surfaceDesc.Format; + + mRenderTargets.resize(mMipLevels, nullptr); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + + mInternalFormat = internalformat; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); + mTextureWidth = width; + mTextureHeight = height; + mMipLevels = mTopLevel + levels; + + mRenderTargets.resize(levels, nullptr); +} + +TextureStorage9_2D::~TextureStorage9_2D() +{ + SafeRelease(mTexture); + for (auto &renderTarget : mRenderTargets) + { + SafeDelete(renderTarget); + } +} + +// Increments refcount on surface. +// caller must Release() the returned surface +gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) +{ + ASSERT(target == GL_TEXTURE_2D); + + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture); + + HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface); + + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); + } + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mTopLevel != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(NULL); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(index.mipIndex < getLevelCount()); + + if (!mRenderTargets[index.mipIndex] && isRenderTarget()) + { + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *surface = NULL; + error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface); + if (error.isError()) + { + return error; + } + + size_t textureMipLevel = mTopLevel + index.mipIndex; + size_t mipWidth = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u); + size_t mipHeight = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u); + + baseTexture->AddRef(); + mRenderTargets[index.mipIndex] = new TextureRenderTarget9( + baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth), + static_cast<GLsizei>(mipHeight), 1, 0); + } + + ASSERT(outRT); + *outRT = mRenderTargets[index.mipIndex]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth), + static_cast<unsigned int>(mTextureHeight), + static_cast<unsigned int>(mMipLevels), getUsage(), + mTextureFormat, getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result); + } + } + + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage); + + int levels = getLevelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer, + EGLImageD3D *image, + RenderTarget9 *renderTarget9) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image) +{ + mInternalFormat = renderTarget9->getInternalFormat(); + mTextureFormat = renderTarget9->getD3DFormat(); + mTextureWidth = renderTarget9->getWidth(); + mTextureHeight = renderTarget9->getHeight(); + mTopLevel = static_cast<int>(renderTarget9->getTextureLevel()); + mMipLevels = mTopLevel + 1; +} + +TextureStorage9_EGLImage::~TextureStorage9_EGLImage() +{ +} + +gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target, + int level, + bool, + IDirect3DSurface9 **outSurface) +{ + ASSERT(target == GL_TEXTURE_2D); + ASSERT(level == 0); + + RenderTargetD3D *renderTargetD3D = nullptr; + gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + if (error.isError()) + { + return error; + } + + RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D); + + *outSurface = renderTarget9->getSurface(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + ASSERT(index.mipIndex == 0); + + return mImage->getRenderTarget(outRT); +} + +gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + RenderTargetD3D *renderTargetD3D = nullptr; + gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + if (error.isError()) + { + return error; + } + + RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D); + *outTexture = renderTarget9->getTexture(); + ASSERT(*outTexture != nullptr); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + ASSERT(getLevelCount() == 1); + + TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage); + + IDirect3DBaseTexture9 *destBaseTexture9 = nullptr; + gl::Error error = dest9->getBaseTexture(&destBaseTexture9); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9); + + IDirect3DSurface9 *destSurface = nullptr; + HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the surface from a texture, result: 0x%X.", result); + } + + RenderTargetD3D *sourceRenderTarget = nullptr; + error = mImage->getRenderTarget(&sourceRenderTarget); + if (error.isError()) + { + SafeRelease(destSurface); + return error; + } + + RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget); + error = + mRenderer->copyToRenderTarget(destSurface, sourceRenderTarget9->getSurface(), isManaged()); + if (error.isError()) + { + SafeRelease(destSurface); + return error; + } + + if (destStorage->getTopLevel() != 0) + { + destTexture9->AddDirtyRect(nullptr); + } + + SafeRelease(destSurface); + return gl::Error(GL_NO_ERROR); +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + for (size_t i = 0; i < CUBE_FACE_COUNT; ++i) + { + mRenderTarget[i] = NULL; + } + + mInternalFormat = internalformat; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + int height = size; + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); + mTextureWidth = size; + mTextureHeight = size; + mMipLevels = mTopLevel + levels; +} + +TextureStorage9_Cube::~TextureStorage9_Cube() +{ + SafeRelease(mTexture); + + for (size_t i = 0; i < CUBE_FACE_COUNT; ++i) + { + SafeDelete(mRenderTarget[i]); + } +} + +// Increments refcount on surface. +// caller must Release() the returned surface +gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) +{ + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture); + + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target); + HRESULT result = texture->GetCubeMapSurface(face, level, outSurface); + + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); + } + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(face, NULL); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(outRT); + ASSERT(index.mipIndex == 0); + ASSERT(index.layerIndex >= 0 && static_cast<size_t>(index.layerIndex) < CUBE_FACE_COUNT); + + if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) + { + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *surface = NULL; + error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, + mTopLevel + index.mipIndex, false, &surface); + if (error.isError()) + { + return error; + } + + baseTexture->AddRef(); + mRenderTarget[index.layerIndex] = new TextureRenderTarget9( + baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat, + static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0); + } + + *outRT = mRenderTarget[index.layerIndex]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + ASSERT(mTextureWidth == mTextureHeight); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateCubeTexture( + static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels), + getUsage(), mTextureFormat, getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); + } + } + + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage); + + int levels = getLevelCount(); + for (int f = 0; f < static_cast<int>(CUBE_FACE_COUNT); f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = + getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h new file mode 100755 index 000000000..f0455a9b7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -0,0 +1,134 @@ +// +// Copyright (c) 2012-2013 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. +// + +// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ + +#include "libANGLE/renderer/d3d/TextureStorage.h" +#include "common/debug.h" + +namespace rx +{ +class EGLImageD3D; +class Renderer9; +class SwapChain9; +class RenderTargetD3D; +class RenderTarget9; + +class TextureStorage9 : public TextureStorage +{ + public: + virtual ~TextureStorage9(); + + static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); + + D3DPOOL getPool() const; + DWORD getUsage() const; + + virtual gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) = 0; + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + bool supportsNativeMipmapFunction() const override; + virtual int getLevelCount() const; + + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + + protected: + int mTopLevel; + size_t mMipLevels; + size_t mTextureWidth; + size_t mTextureHeight; + GLenum mInternalFormat; + D3DFORMAT mTextureFormat; + + Renderer9 *mRenderer; + + TextureStorage9(Renderer9 *renderer, DWORD usage); + + private: + const DWORD mD3DUsage; + const D3DPOOL mD3DPool; +}; + +class TextureStorage9_2D : public TextureStorage9 +{ + public: + TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorage9_2D(); + + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + private: + IDirect3DTexture9 *mTexture; + std::vector<RenderTarget9 *> mRenderTargets; +}; + +class TextureStorage9_EGLImage final : public TextureStorage9 +{ + public: + TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9); + ~TextureStorage9_EGLImage() override; + + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override; + gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(TextureStorage *destStorage) override; + + private: + EGLImageD3D *mImage; +}; + +class TextureStorage9_Cube : public TextureStorage9 +{ + public: + TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual ~TextureStorage9_Cube(); + + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + private: + static const size_t CUBE_FACE_COUNT = 6; + + IDirect3DCubeTexture9 *mTexture; + RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ + diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h new file mode 100755 index 000000000..28b8717e6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -0,0 +1,29 @@ +// +// Copyright 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. +// + +// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ + +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Renderer9; + +class VertexArray9 : public VertexArrayImpl +{ + public: + VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {} + + virtual ~VertexArray9() { } +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp new file mode 100755 index 000000000..c5c07c348 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -0,0 +1,165 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. + +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/Buffer.h" + +namespace rx +{ + +VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer9::~VertexBuffer9() +{ + SafeRelease(mVertexBuffer); +} + +gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mVertexBuffer); + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) +{ + if (!mVertexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib)); + int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib)); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + uint8_t *mapPtr = nullptr; + + auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, count, instances); + if (errorOrMapSize.isError()) + { + return errorOrMapSize.getError(); + } + + unsigned int mapSize = errorOrMapSize.getResult(); + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result); + } + + const uint8_t *input = sourceData; + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); + const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType); + bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; + + if (!needsConversion && inputStride == elementSize) + { + size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride); + memcpy(mapPtr, input, copySize); + } + else + { + d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); + } + + mVertexBuffer->Unlock(); + + return gl::Error(GL_NO_ERROR); +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error VertexBuffer9::discard() +{ + if (!mVertexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result); + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result); + } + + return gl::Error(GL_NO_ERROR); +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h new file mode 100755 index 000000000..0d2d8c288 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2002-2012 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. +// + +// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ + +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(Renderer9 *renderer); + + gl::Error initialize(unsigned int size, bool dynamicUsage) override; + + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) override; + + unsigned int getBufferSize() const override; + gl::Error setBufferSize(unsigned int size) override; + gl::Error discard() override; + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + ~VertexBuffer9() override; + Renderer9 *mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp new file mode 100755 index 000000000..c2e935e71 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -0,0 +1,255 @@ +// +// Copyright (c) 2012 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. +// + +// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. + +#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" + +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +namespace rx +{ + +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].lruCount = 0; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; +} + +VertexDeclarationCache::~VertexDeclarationCache() +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + SafeRelease(mVertexDeclCache[i].vertexDeclaration); + } +} + +gl::Error VertexDeclarationCache::applyDeclaration( + IDirect3DDevice9 *device, + const std::vector<TranslatedAttribute> &attributes, + gl::Program *program, + GLint start, + GLsizei instances, + GLsizei *repeatDraw) +{ + ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size()); + + *repeatDraw = 1; + + const size_t invalidAttribIndex = attributes.size(); + size_t indexedAttribute = invalidAttribIndex; + size_t instancedAttribute = invalidAttribIndex; + + if (instances == 0) + { + for (size_t i = 0; i < attributes.size(); ++i) + { + if (attributes[i].divisor != 0) + { + // If a divisor is set, it still applies even if an instanced draw was not used, so treat + // as a single-instance draw. + instances = 1; + break; + } + } + } + + if (instances > 0) + { + // Find an indexed attribute to be mapped to D3D stream 0 + for (size_t i = 0; i < attributes.size(); i++) + { + if (attributes[i].active) + { + if (indexedAttribute == invalidAttribIndex && attributes[i].divisor == 0) + { + indexedAttribute = i; + } + else if (instancedAttribute == invalidAttribIndex && attributes[i].divisor != 0) + { + instancedAttribute = i; + } + if (indexedAttribute != invalidAttribIndex && instancedAttribute != invalidAttribIndex) + break; // Found both an indexed and instanced attribute + } + } + + // The validation layer checks that there is at least one active attribute with a zero divisor as per + // the GL_ANGLE_instanced_arrays spec. + ASSERT(indexedAttribute != invalidAttribIndex || !attributes.size()); + } + + D3DCAPS9 caps; + device->GetDeviceCaps(&caps); + + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + const auto &semanticIndexes = programD3D->getAttribLocationToD3DSemantics(); + + for (size_t i = 0; i < attributes.size(); i++) + { + if (attributes[i].active) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(attributes[i].storage == NULL); + + int stream = static_cast<int>(i); + + if (instances > 0) + { + // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. + if (instancedAttribute == invalidAttribIndex) + { + *repeatDraw = instances; + } + else + { + if (i == indexedAttribute) + { + stream = 0; + } + else if (i == 0) + { + stream = static_cast<int>(indexedAttribute); + } + + UINT frequency = 1; + + if (attributes[i].divisor == 0) + { + frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; + } + else + { + frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; + } + + device->SetStreamSourceFreq(stream, frequency); + mInstancingEnabled = true; + } + } + + VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer.get()); + + unsigned int offset = 0; + ANGLE_TRY_RESULT(attributes[i].computeOffset(start), offset); + + if (mAppliedVBs[stream].serial != attributes[i].serial || + mAppliedVBs[stream].stride != attributes[i].stride || + mAppliedVBs[stream].offset != offset) + { + device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset, + attributes[i].stride); + mAppliedVBs[stream].serial = attributes[i].serial; + mAppliedVBs[stream].stride = attributes[i].stride; + mAppliedVBs[stream].offset = offset; + } + + gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatType); + + element->Stream = static_cast<WORD>(stream); + element->Offset = 0; + element->Type = static_cast<BYTE>(d3d9VertexInfo.nativeFormat); + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = static_cast<BYTE>(semanticIndexes[i]); + element++; + } + } + + if (instances == 0 || instancedAttribute == invalidAttribIndex) + { + if (mInstancingEnabled) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } + + mInstancingEnabled = false; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *(element++) = end; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) + { + entry->lruCount = ++mMaxLru; + if(entry->vertexDeclaration != mLastSetVDecl) + { + device->SetVertexDeclaration(entry->vertexDeclaration); + mLastSetVDecl = entry->vertexDeclaration; + } + + return gl::Error(GL_NO_ERROR); + } + } + + VertexDeclCacheEntry *lastCache = mVertexDeclCache; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) + { + lastCache = &mVertexDeclCache[i]; + } + } + + if (lastCache->vertexDeclaration != NULL) + { + SafeRelease(lastCache->vertexDeclaration); + // mLastSetVDecl is set to the replacement, so we don't have to worry + // about it. + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result); + } + + device->SetVertexDeclaration(lastCache->vertexDeclaration); + mLastSetVDecl = lastCache->vertexDeclaration; + lastCache->lruCount = ++mMaxLru; + + return gl::Error(GL_NO_ERROR); +} + +void VertexDeclarationCache::markStateDirty() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; // Forces it to be disabled when not used +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h new file mode 100755 index 000000000..7bd7cabae --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2012 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. +// + +// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +namespace gl +{ +class VertexDataManager; +class Program; +} + +namespace rx +{ + +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + gl::Error applyDeclaration(IDirect3DDevice9 *device, + const std::vector<TranslatedAttribute> &attributes, + gl::Program *program, + GLint start, + GLsizei instances, + GLsizei *repeatDraw); + + void markStateDirty(); + + private: + UINT mMaxLru; + + enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; + + struct VBData + { + unsigned int serial; + unsigned int stride; + unsigned int offset; + }; + + VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; + IDirect3DVertexDeclaration9 *mLastSetVDecl; + bool mInstancingEnabled; + + struct VertexDeclCacheEntry + { + D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; + UINT lruCount; + IDirect3DVertexDeclaration9 *vertexDeclaration; + } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp new file mode 100755 index 000000000..7cff9a117 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -0,0 +1,659 @@ +// +// Copyright (c) 2013-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. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.h" + +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" + +using namespace angle; + +namespace rx +{ + +namespace d3d9 +{ + +constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +// A map to determine the pixel size and mip generation function of a given D3D format +typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap; + +constexpr D3DFormat::D3DFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + redBits(0), + greenBits(0), + blueBits(0), + alphaBits(0), + luminanceBits(0), + depthBits(0), + stencilBits(0), + formatID(angle::Format::ID::NONE) +{ +} + +constexpr D3DFormat::D3DFormat(GLuint bits, + GLuint blockWidth, + GLuint blockHeight, + GLuint redBits, + GLuint greenBits, + GLuint blueBits, + GLuint alphaBits, + GLuint lumBits, + GLuint depthBits, + GLuint stencilBits, + Format::ID formatID) + : pixelBytes(bits / 8), + blockWidth(blockWidth), + blockHeight(blockHeight), + redBits(redBits), + greenBits(greenBits), + blueBits(blueBits), + alphaBits(alphaBits), + luminanceBits(lumBits), + depthBits(depthBits), + stencilBits(stencilBits), + formatID(formatID) +{ +} + +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) +{ + if (format == D3DFMT_NULL) + { + static constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE); + return info; + } + + if (format == D3DFMT_INTZ) + { + static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, + Format::ID::D24_UNORM_S8_UINT); + return info; + } + + switch (format) + { + case D3DFMT_UNKNOWN: + { + static constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE); + return info; + } + + case D3DFMT_L8: + { + static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, Format::ID::L8_UNORM); + return info; + } + case D3DFMT_A8: + { + static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, Format::ID::A8_UNORM); + return info; + } + case D3DFMT_A8L8: + { + static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, Format::ID::L8A8_UNORM); + return info; + } + + case D3DFMT_A4R4G4B4: + { + static constexpr D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0, + Format::ID::B4G4R4A4_UNORM); + return info; + } + case D3DFMT_A1R5G5B5: + { + static constexpr D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0, + Format::ID::B5G5R5A1_UNORM); + return info; + } + case D3DFMT_R5G6B5: + { + static constexpr D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0, + Format::ID::R5G6B5_UNORM); + return info; + } + case D3DFMT_X8R8G8B8: + { + static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0, + Format::ID::B8G8R8X8_UNORM); + return info; + } + case D3DFMT_A8R8G8B8: + { + static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0, + Format::ID::B8G8R8A8_UNORM); + return info; + } + + case D3DFMT_R16F: + { + static constexpr D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, Format::ID::R16_FLOAT); + return info; + } + case D3DFMT_G16R16F: + { + static constexpr D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0, + Format::ID::R16G16_FLOAT); + return info; + } + case D3DFMT_A16B16G16R16F: + { + static constexpr D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0, + Format::ID::R16G16B16A16_FLOAT); + return info; + } + case D3DFMT_R32F: + { + static constexpr D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, Format::ID::R32_FLOAT); + return info; + } + case D3DFMT_G32R32F: + { + static constexpr D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0, + Format::ID::R32G32_FLOAT); + return info; + } + case D3DFMT_A32B32G32R32F: + { + static constexpr D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0, + Format::ID::R32G32B32A32_FLOAT); + return info; + } + + case D3DFMT_D16: + { + static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, Format::ID::D16_UNORM); + return info; + } + case D3DFMT_D24S8: + { + static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, + Format::ID::D24_UNORM_S8_UINT); + return info; + } + case D3DFMT_D24X8: + { + static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, Format::ID::D16_UNORM); + return info; + } + case D3DFMT_D32: + { + static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, Format::ID::D32_UNORM); + return info; + } + + case D3DFMT_DXT1: + { + static constexpr D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC1_RGBA_UNORM_BLOCK); + return info; + } + case D3DFMT_DXT3: + { + static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC2_RGBA_UNORM_BLOCK); + return info; + } + case D3DFMT_DXT5: + { + static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC3_RGBA_UNORM_BLOCK); + return info; + } + + default: + { + static constexpr D3DFormat defaultInfo; + return defaultInfo; + } + } +} + +typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair; +typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + using namespace angle; // For image initialization functions + + InternalFormatInitialzerMap map; + + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>)); + + return map; +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +typedef std::pair<GLenum, TextureFormat> D3D9FormatPair; +typedef std::map<GLenum, TextureFormat> D3D9FormatMap; + +TextureFormat::TextureFormat() + : texFormat(D3DFMT_UNKNOWN), + renderFormat(D3DFMT_UNKNOWN), + dataInitializerFunction(NULL), + loadFunction(UnreachableLoad) +{ +} + +static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, + D3DFORMAT renderFormat, LoadImageFunction loadFunction) +{ + TextureFormat info; + info.texFormat = texFormat; + info.renderFormat = renderFormat; + + static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); + info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; + + info.loadFunction = loadFunction; + + map->insert(std::make_pair(internalFormat, info)); +} + +static D3D9FormatMap BuildD3D9FormatMap() +{ + using namespace angle; // For image loading functions + + D3D9FormatMap map; + + // clang-format off + // | Internal format | Texture format | Render format | Load function | + InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); + + // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely + // supported. We're allowed to do this because: + // - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format + // resolutions of our own choosing. + // - OES_depth_texture states that downsampling of the depth formats is allowed. + // - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it + // introduces. + // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed. + + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D24X8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? + + InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative<GLfloat, 4> ); + InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4<GLfloat, gl::Float32One>); + InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative<GLfloat, 2> ); + InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative<GLfloat, 1> ); + InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); + + InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative<GLhalf, 4> ); + InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4<GLhalf, gl::Float16One> ); + InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative<GLhalf, 2> ); + InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative<GLhalf, 1> ); + InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); + + InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadA8ToBGRA8 ); + + InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); + + InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative<GLubyte, 4> ); + InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); + + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_L8, LoadToNative<GLubyte, 1> ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_A8L8, LoadToNative<GLubyte, 2> ); + // clang-format on + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +{ + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +struct TranslationDescription +{ + DWORD capsFlag; + VertexFormat preferredConversion; + VertexFormat fallbackConversion; +}; + +// Mapping from OpenGL-ES vertex attrib type to D3D decl type: +// +// BYTE SHORT (Cast) +// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) +// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) +// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) +// SHORT SHORT (Identity) +// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) +// UNSIGNED_SHORT FLOAT (Cast) +// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) +// FIXED (not in WebGL) FLOAT (FixedToFloat) +// FLOAT FLOAT (Identity) + +// GLToCType maps from GL type (as GLenum) to the C typedef. +template <GLenum GLType> struct GLToCType { }; + +template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; }; +template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; }; +template <> struct GLToCType<GL_SHORT> { typedef GLshort type; }; +template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; }; +template <> struct GLToCType<GL_FIXED> { typedef GLuint type; }; +template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; }; + +// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) +enum D3DVertexType +{ + D3DVT_FLOAT, + D3DVT_SHORT, + D3DVT_SHORT_NORM, + D3DVT_UBYTE, + D3DVT_UBYTE_NORM, + D3DVT_USHORT_NORM +}; + +// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. +template <unsigned int D3DType> struct D3DToCType { }; + +template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; }; +template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; }; +template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; }; +template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; }; +template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; }; +template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; }; + +// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. +template <unsigned int type, int size> struct WidenRule { }; + +template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { }; +template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { }; +template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { }; +template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { }; +template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { }; +template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { }; + +// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. +template <unsigned int d3dtype, int size> struct VertexTypeFlags { }; + +template <unsigned int _capflag, unsigned int _declflag> +struct VertexTypeFlagsHelper +{ + enum { capflag = _capflag }; + enum { declflag = _declflag }; +}; + +template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; +template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; +template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; +template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; +template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; +template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; +template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { }; +template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { }; +template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { }; +template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { }; +template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { }; +template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { }; + + +// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). +template <GLenum GLtype, bool normalized> struct VertexTypeMapping { }; + +template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred> +struct VertexTypeMappingBase +{ + enum { preferred = Preferred }; + enum { fallback = Fallback }; +}; + +template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast +template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize +template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast +template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize +template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity +template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize +template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast +template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize +template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat +template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity + + +// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). +// The conversion rules themselves are defined in vertexconversion.h. + +// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping). +template <GLenum fromType, bool normalized, unsigned int toType> +struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { }; + +// All conversions from normalized types to float use the Normalize operator. +template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { }; + +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; +template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; + +// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) +// whether it is normalized or not. +template <class T, bool normalized> struct DefaultVertexValuesStage2 { }; + +template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { }; +template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { }; + +// Work out the default value rule for a D3D type (expressed as the C type) and +template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { }; +template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { }; + +// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. +// The fallback conversion produces an output that all D3D9 devices must support. +template <class T> struct UsePreferred { enum { type = T::preferred }; }; +template <class T> struct UseFallback { enum { type = T::fallback }; }; + +// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, +// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag +// and the D3DDECLTYPE member needed for the vertex declaration in declflag. +template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule> +struct Converter + : VertexDataConverter< + typename GLToCType<fromType>::type, + WidenRule<PreferenceRule<VertexTypeMapping<fromType, normalized>>::type, size>, + ConversionRule<fromType, + normalized, + PreferenceRule<VertexTypeMapping<fromType, normalized>>::type>, + DefaultVertexValues<typename D3DToCType<PreferenceRule< + VertexTypeMapping<fromType, normalized>>::type>::type, + normalized>> +{ +private: + enum + { + d3dtype = PreferenceRule<VertexTypeMapping<fromType, normalized>>::type + }; + enum + { + d3dsize = WidenRule<d3dtype, size>::finalWidth + }; + +public: + enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag }; + enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag }; +}; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + outputElementSize(0), + copyFunction(NULL), + nativeFormat(D3DDECLTYPE_UNUSED), + componentType(GL_NONE) +{ +} + +// Initialize a TranslationInfo +VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat) +{ + VertexFormat formatInfo; + formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; + formatInfo.outputElementSize = elementSize; + formatInfo.copyFunction = copyFunc; + formatInfo.nativeFormat = nativeFormat; + formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); + return formatInfo; +} + +#define TRANSLATION(type, norm, size, preferred) \ + CreateVertexFormatInfo \ + ( \ + Converter<type, norm, size, preferred>::identity, \ + Converter<type, norm, size, preferred>::finalSize, \ + Converter<type, norm, size, preferred>::convertArray, \ + static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \ + ) + +#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ + { \ + Converter<type, norm, size, UsePreferred>::capflag, \ + TRANSLATION(type, norm, size, UsePreferred), \ + TRANSLATION(type, norm, size, UseFallback) \ + } + +#define TRANSLATIONS_FOR_TYPE(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ + } + +#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + } + +static inline unsigned int ComputeTypeIndex(GLenum type) +{ + switch (type) + { + case GL_BYTE: return 0; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 3; + case GL_FIXED: return 4; + case GL_FLOAT: return 5; + + default: UNREACHABLE(); return 5; + } +} + +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType) +{ + static bool initialized = false; + static DWORD initializedDeclTypes = 0; + static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + if (initializedDeclTypes != supportedDeclTypes) + { + const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] + { + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) + }; + for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + for (unsigned int k = 0; k < 4; k++) + { + if (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) + { + formatConverters[i][j][k] = translations[i][j][k].preferredConversion; + } + else + { + formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; + } + } + } + } + initialized = true; + initializedDeclTypes = supportedDeclTypes; + } + + const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); + + // Pure integer attributes only supported in ES3.0 + ASSERT(!vertexFormat.pureInteger); + return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized][vertexFormat.components - 1]; +} + +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h new file mode 100755 index 000000000..828252d33 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2013-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. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D9 +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ + +#include <map> + +#include "common/platform.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/Format.h" +#include "libANGLE/renderer/renderer_utils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" + +namespace rx +{ + +class Renderer9; + +namespace d3d9 +{ + +struct D3DFormat +{ + constexpr D3DFormat(); + constexpr D3DFormat(GLuint pixelBytes, + GLuint blockWidth, + GLuint blockHeight, + GLuint redBits, + GLuint greenBits, + GLuint blueBits, + GLuint alphaBits, + GLuint luminanceBits, + GLuint depthBits, + GLuint stencilBits, + angle::Format::ID formatID); + + const angle::Format &info() const { return angle::Format::Get(formatID); } + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; + + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + GLuint alphaBits; + GLuint luminanceBits; + + GLuint depthBits; + GLuint stencilBits; + + angle::Format::ID formatID; +}; + +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); + +struct VertexFormat +{ + VertexFormat(); + + VertexConversionType conversionType; + size_t outputElementSize; + VertexCopyFunction copyFunction; + D3DDECLTYPE nativeFormat; + GLenum componentType; +}; +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType); + +struct TextureFormat +{ + TextureFormat(); + + D3DFORMAT texFormat; + D3DFORMAT renderFormat; + + InitializeTextureDataFunction dataInitializerFunction; + + LoadImageFunction loadFunction; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); + +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp new file mode 100755 index 000000000..a6e1f239d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -0,0 +1,659 @@ +// +// Copyright (c) 2002-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. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" + +#include "common/mathutil.h" +#include "common/debug.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" +#include "libANGLE/renderer/driver_utils.h" + +#include "third_party/systeminfo/SystemInfo.h" + +namespace rx +{ + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::ColorF color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; + case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + switch (cubeFace) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + face = D3DCUBEMAP_FACE_POSITIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + face = D3DCUBEMAP_FACE_NEGATIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + face = D3DCUBEMAP_FACE_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + face = D3DCUBEMAP_FACE_POSITIVE_Z; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = D3DCUBEMAP_FACE_NEGATIVE_Z; + break; + default: UNREACHABLE(); + } + + return face; +} + +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + return (red ? D3DCOLORWRITEENABLE_RED : 0) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3DTEXF_ANISOTROPIC; + } + + D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; + switch (magFilter) + { + case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; + case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; + default: UNREACHABLE(); + } + + return d3dMagFilter; +} + +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, + float *d3dLodBias, float maxAnisotropy, size_t baseLevel) +{ + switch (minFilter) + { + case GL_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + default: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + UNREACHABLE(); + } + + // Disabling mipmapping will always sample from level 0 of the texture. It is possible to work + // around this by modifying D3DSAMP_MAXMIPLEVEL to force a specific mip level to become the + // lowest sampled mip level and using a large negative value for D3DSAMP_MIPMAPLODBIAS to + // ensure that only the base mip level is sampled. + if (baseLevel > 0 && *d3dMipFilter == D3DTEXF_NONE) + { + *d3dMipFilter = D3DTEXF_POINT; + *d3dLodBias = -static_cast<float>(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + } + else + { + *d3dLodBias = 0.0f; + } + + if (maxAnisotropy > 1.0f) + { + *d3dMinFilter = D3DTEXF_ANISOTROPIC; + } +} + +D3DQUERYTYPE ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + return D3DQUERYTYPE_OCCLUSION; + case GL_COMMANDS_COMPLETED_CHROMIUM: + return D3DQUERYTYPE_EVENT; + default: + UNREACHABLE(); + return static_cast<D3DQUERYTYPE>(0); + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) +{ + return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE; +} + +} + +namespace d3d9_gl +{ + +unsigned int GetReservedVertexUniformVectors() +{ + return 3; // dx_ViewCoords, dx_ViewAdjust and dx_DepthRange. +} + +unsigned int GetReservedFragmentUniformVectors() +{ + return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. +} + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) +{ + return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).info().glInternalFormat; + GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format; + return convertedFormat == format; +} + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, + UINT adapter, D3DFORMAT adapterFormat) +{ + gl::TextureCaps textureCaps; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + + if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN) + { + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + else + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); + } + + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + + if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN) + { + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + + if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable) + { + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + } + + textureCaps.sampleCounts.insert(1); + for (unsigned int i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + { + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } + } + } + + return textureCaps; +} + +void GenerateCaps(IDirect3D9 *d3d9, + IDirect3DDevice9 *device, + D3DDEVTYPE deviceType, + UINT adapter, + gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, + gl::Limitations *limitations) +{ + D3DCAPS9 deviceCaps; + if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) + { + // Can't continue with out device caps + return; + } + + D3DDISPLAYMODE currentDisplayMode; + d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); + + GLuint maxSamples = 0; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, + currentDisplayMode.Format); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + // GL core feature limits + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); + + // 3D textures are unimplemented in D3D9 + caps->max3DTextureSize = 1; + + // Only one limit in GL, use the minimum dimension + caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); + + // D3D treats cube maps as a special case of 2D textures + caps->maxCubeMapTextureSize = caps->max2DTextureSize; + + // Array textures are not available in D3D9 + caps->maxArrayTextureLayers = 1; + + // ES3-only feature + caps->maxLODBias = 0.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Draw buffers are not supported in D3D9 + caps->maxDrawBuffers = 1; + caps->maxColorAttachments = 1; + + // No specific limits on viewport size, maximum 2D texture size is equivalent + caps->maxViewportWidth = caps->max2DTextureSize; + caps->maxViewportHeight = caps->maxViewportWidth; + + // Point size is clamped to 1.0f when the shader model is less than 3 + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits (unused in ES2) + caps->maxElementsIndices = 0; + caps->maxElementsVertices = 0; + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // Some (most) hardware only supports single-precision floating-point numbers, + // which can accurately represent integers up to +/-16777216 + caps->vertexHighpInt.setSimulatedInt(24); + caps->vertexMediumpInt.setSimulatedInt(24); + caps->vertexLowpInt.setSimulatedInt(24); + caps->fragmentHighpInt.setSimulatedInt(24); + caps->fragmentMediumpInt.setSimulatedInt(24); + caps->fragmentLowpInt.setSimulatedInt(24); + + // WaitSync is ES3-only, set to zero + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = 16; + + const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; + caps->maxVertexUniformVectors = + MAX_VERTEX_CONSTANT_VECTORS_D3D9 - GetReservedVertexUniformVectors(); + caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4; + + caps->maxVertexUniformBlocks = 0; + + // SM3 only supports 11 output variables, with a special 12th register for PSIZE. + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9; + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7; + caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3 + : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4; + + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F))) + { + const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4; + caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3; + } + else + { + caps->maxVertexTextureImageUnits = 0; + } + + // Fragment shader limits + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224; + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32; + caps->maxFragmentUniformVectors = + ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 + : MAX_PIXEL_CONSTANT_VECTORS_SM2) - + GetReservedFragmentUniformVectors(); + caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4; + caps->maxFragmentUniformBlocks = 0; + caps->maxFragmentInputComponents = caps->maxVertexOutputComponents; + caps->maxTextureImageUnits = 16; + caps->minProgramTexelOffset = 0; + caps->maxProgramTexelOffset = 0; + + // Aggregate shader limits (unused in ES2) + caps->maxUniformBufferBindings = 0; + caps->maxUniformBlockSize = 0; + caps->uniformBufferOffsetAlignment = 0; + caps->maxCombinedUniformBlocks = 0; + caps->maxCombinedVertexUniformComponents = 0; + caps->maxCombinedFragmentUniformComponents = 0; + caps->maxVaryingComponents = 0; + + // Aggregate shader limits + caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4; + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = 0; + caps->maxTransformFeedbackSeparateAttributes = 0; + caps->maxTransformFeedbackSeparateComponents = 0; + + // Multisample limits + caps->maxSamples = maxSamples; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = false; + extensions->mapBuffer = false; + extensions->mapBufferRange = false; + + // textureRG is emulated and not performant. + extensions->textureRG = false; + + D3DADAPTER_IDENTIFIER9 adapterId = {}; + if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) + { + // ATI cards on XP have problems with non-power-of-two textures. + extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(!isWindowsVistaOrGreater() && IsAMD(adapterId.VendorId)); + + // Disable depth texture support on AMD cards (See ANGLE issue 839) + if (IsAMD(adapterId.VendorId)) + { + extensions->depthTextures = false; + } + } + else + { + extensions->textureNPOT = false; + } + + extensions->drawBuffers = false; + extensions->textureStorage = true; + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; + extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy); + + // Check occlusion query support by trying to create one + IDirect3DQuery9 *occlusionQuery = NULL; + extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; + SafeRelease(occlusionQuery); + + // Check event query support by trying to create one + IDirect3DQuery9 *eventQuery = NULL; + extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; + SafeRelease(eventQuery); + + extensions->timerQuery = false; // Unimplemented + extensions->disjointTimerQuery = false; + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; + extensions->translatedShaderSource = true; + extensions->fboRenderMipmap = false; + extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint + extensions->colorBufferFloat = false; + extensions->debugMarker = true; + extensions->eglImage = true; + extensions->eglImageExternal = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->syncQuery = extensions->fence; + + // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil + // state. + limitations->noSeparateStencilRefsAndMasks = true; + + // D3D9 shader models have limited support for looping, so the Appendix A + // index/loop limitations are necessary. Workarounds that are needed to + // support dynamic indexing of vectors on HLSL also don't work on D3D9. + limitations->shadersRequireIndexedLoopValidation = true; + + // D3D9 cannot support constant color and alpha blend funcs together + limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true; +} + +} + +namespace d3d9 +{ + +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth; + GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight; + return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight); +} + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast<GLsizei>(d3dFormatInfo.blockWidth) || + *requestHeight < static_cast<GLsizei>(d3dFormatInfo.blockHeight)) + { + while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +WorkaroundsD3D GenerateWorkarounds() +{ + WorkaroundsD3D workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = false; + workarounds.useInstancedPointSpriteEmulation = false; + + // TODO(jmadill): Disable workaround when we have a fixed compiler DLL. + workarounds.expandIntegerPowExpressions = true; + + return workarounds; +} + +} // namespace d3d9 + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h new file mode 100755 index 000000000..ff6d55fd5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2002-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. +// + +// renderer9_utils.h: Conversion functions and other utility routines +// specific to the D3D9 renderer + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ + +#include "common/Color.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +class RenderTarget9; +struct WorkaroundsD3D; + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::ColorF color); +D3DBLEND ConvertBlendFunc(GLenum blend); +D3DBLENDOP ConvertBlendOp(GLenum blendOp); +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, + float *d3dLodBias, float maxAnisotropy, size_t baseLevel); +D3DQUERYTYPE ConvertQueryType(GLenum queryType); + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); + +} + +namespace d3d9_gl +{ + +unsigned int GetReservedVertexUniformVectors(); + +unsigned int GetReservedFragmentUniformVectors(); + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + +void GenerateCaps(IDirect3D9 *d3d9, + IDirect3DDevice9 *device, + D3DDEVTYPE deviceType, + UINT adapter, + gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, + gl::Limitations *limitations); +} + +namespace d3d9 +{ + +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height); + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case D3DERR_DRIVERINTERNALERROR: + case D3DERR_DEVICELOST: + case D3DERR_DEVICEHUNG: + case D3DERR_DEVICEREMOVED: + return true; + default: + return false; + } +} + +WorkaroundsD3D GenerateWorkarounds(); +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps new file mode 100755 index 000000000..dc357d0fa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps @@ -0,0 +1,33 @@ +// +// Copyright (c) 2012 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. +// + +sampler2D tex : s0; + +uniform float4 mult : c0; +uniform float4 add : c1; + +// Passthrough Pixel Shader +// Outputs texture 0 sampled at texcoord 0. +float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy); +}; + +// Luminance Conversion Pixel Shader +// Performs a mad operation using the LA data from the texture with mult.xw and add.xw. +// Returns data in the form of llla +float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR +{ + return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; +}; + +// RGB/A Component Mask Pixel Shader +// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. +// Returns data in the form of rgba +float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy) * mult + add; +}; diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs new file mode 100755 index 000000000..3a36980b9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 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. +// + +struct VS_OUTPUT +{ + float4 position : POSITION; + float4 texcoord : TEXCOORD0; +}; + +uniform float4 halfPixelSize : c0; + +// Standard Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. +// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. +VS_OUTPUT standardvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; + +// Flip Y Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. +// C0.XY must be the half-pixel width and height. C0.ZW must be 0. +VS_OUTPUT flipyvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h new file mode 100755 index 000000000..24482d755 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h @@ -0,0 +1,84 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 4 instruction slots used (1 texture, 3 arithmetic)
+#endif
+
+const BYTE g_ps20_componentmaskps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 50, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 143, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 136, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 108, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 113, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 120, 0, 0, 0,
+ 0, 0, 0, 0, 97, 100,
+ 100, 0, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 109, 117, 108, 116, 0, 116,
+ 101, 120, 0, 171, 171, 171,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 171, 171, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 3, 176, 31, 0,
+ 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 1, 0, 0, 2,
+ 1, 0, 15, 128, 0, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 1, 0, 228, 128,
+ 1, 0, 228, 160, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h new file mode 100755 index 000000000..5eb513132 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h @@ -0,0 +1,66 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, 1, 0, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xxyy, c1.xxzz
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_flipyvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 97, 108, 102, 80, 105,
+ 120, 101, 108, 83, 105, 122,
+ 101, 0, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 171, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 63, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 2, 0, 0, 3,
+ 0, 0, 15, 192, 0, 0,
+ 228, 144, 0, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 224, 0, 0, 228, 144,
+ 1, 0, 80, 160, 1, 0,
+ 160, 160, 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h new file mode 100755 index 000000000..bdd25ac13 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h @@ -0,0 +1,94 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r1.xw, c0
+ mad r0.x, r0.x, r1.x, c1.x
+ mad r0.y, r0.w, r1.w, c1.w
+ mov r1.xyz, r0.x
+ mov r1.w, r0.y
+ mov oC0, r1
+
+// approximately 7 instruction slots used (1 texture, 6 arithmetic)
+#endif
+
+const BYTE g_ps20_luminanceps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 50, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 143, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 136, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 0, 0, 92, 0,
+ 0, 0, 0, 0, 0, 0,
+ 108, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 113, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 120, 0, 0, 0,
+ 0, 0, 0, 0, 97, 100,
+ 100, 0, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 109, 117, 108, 116, 0, 116,
+ 101, 120, 0, 171, 171, 171,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 171, 171, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 3, 176, 31, 0,
+ 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 1, 0, 0, 2,
+ 1, 0, 9, 128, 0, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 1, 0, 0, 128,
+ 1, 0, 0, 160, 4, 0,
+ 0, 4, 0, 0, 2, 128,
+ 0, 0, 255, 128, 1, 0,
+ 255, 128, 1, 0, 255, 160,
+ 1, 0, 0, 2, 1, 0,
+ 7, 128, 0, 0, 0, 128,
+ 1, 0, 0, 2, 1, 0,
+ 8, 128, 0, 0, 85, 128,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 1, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h new file mode 100755 index 000000000..337af92ec --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h @@ -0,0 +1,61 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+#endif
+
+const BYTE g_ps20_passthroughps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 33, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 75, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 68, 0, 0, 0, 48, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 52, 0,
+ 0, 0, 0, 0, 0, 0,
+ 116, 101, 120, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 171, 171, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h new file mode 100755 index 000000000..a83050d8c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h @@ -0,0 +1,66 @@ +#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, -0.5, 1, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xyzz, c1.xxww
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_standardvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 97, 108, 102, 80, 105,
+ 120, 101, 108, 83, 105, 122,
+ 101, 0, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171,
+ 171, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 63, 0, 0, 0, 191,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 2, 0, 0, 3,
+ 0, 0, 15, 192, 0, 0,
+ 228, 144, 0, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 224, 0, 0, 228, 144,
+ 1, 0, 164, 160, 1, 0,
+ 240, 160, 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat new file mode 100755 index 000000000..19a99ba91 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat @@ -0,0 +1,63 @@ +@ECHO OFF
+REM
+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+setlocal
+set errorCount=0
+set successCount=0
+set debug=0
+
+if "%1" == "debug" (
+ set debug=1
+)
+if "%1" == "release" (
+ set debug=0
+)
+
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Blit.vs standardvs vs_2_0 compiled\standardvs.h %debug%
+call:BuildShader Blit.vs flipyvs vs_2_0 compiled\flipyvs.h %debug%
+call:BuildShader Blit.ps passthroughps ps_2_0 compiled\passthroughps.h %debug%
+call:BuildShader Blit.ps luminanceps ps_2_0 compiled\luminanceps.h %debug%
+call:BuildShader Blit.ps componentmaskps ps_2_0 compiled\componentmaskps.h %debug%
+
+echo.
+
+if %successCount% GTR 0 (
+ echo %successCount% shaders compiled successfully.
+)
+if %errorCount% GTR 0 (
+ echo There were %errorCount% shader compilation errors.
+)
+
+endlocal
+exit /b
+
+:BuildShader
+set input=%~1
+set entry=%~2
+set type=%~3
+set output=%~4
+set debug=%~5
+
+if %debug% == 0 (
+ set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"
+) else (
+ set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"
+)
+
+set error=0
+%buildCMD% || set error=1
+
+if %error% == 0 (
+ set /a successCount=%successCount%+1
+) else (
+ set /a errorCount=%errorCount%+1
+)
+
+exit /b
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h new file mode 100755 index 000000000..aa05934bc --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h @@ -0,0 +1,200 @@ +// +// Copyright (c) 2002-2010 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. +// + +// vertexconversion.h: A library of vertex conversion classes that can be used to build +// the FormatConverter objects used by the buffer conversion system. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ + +#include <limits> +#include <cstdint> +#include <cstddef> + +namespace rx +{ + +// Conversion types: +// static const bool identity: true if this is an identity transform, false otherwise +// static U convert(T): convert a single element from the input type to the output type +// typedef ... OutputType: the type produced by this conversion + +template <class T> +struct Identity +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return x; + } +}; + +template <class FromT, class ToT> +struct Cast +{ + static const bool identity = false; + + typedef ToT OutputType; + + static ToT convert(FromT x) + { + return static_cast<ToT>(x); + } +}; + +template <class T> +struct Cast<T, T> +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return static_cast<T>(x); + } +}; + +template <class T> +struct Normalize +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(T x) + { + typedef std::numeric_limits<T> NL; + float f = static_cast<float>(x); + + if (NL::is_signed) + { + // const float => VC2008 computes it at compile time + // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. + const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1); + return (2*f+1)*divisor; + } + else + { + return f/NL::max(); + } + } +}; + +template <class FromType, std::size_t ScaleBits> +struct FixedToFloat +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(FromType x) + { + const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits); + return static_cast<float>(x) * divisor; + } +}; + +// Widen types: +// static const unsigned int initialWidth: number of components before conversion +// static const unsigned int finalWidth: number of components after conversion + +// Float is supported at any size. +template <std::size_t N> +struct NoWiden +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N; +}; + +// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components +template <std::size_t N> +struct WidenToEven +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N+(N&1); +}; + +template <std::size_t N> +struct WidenToFour +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = 4; +}; + +// Most types have 0 and 1 that are just that. +template <class T> +struct SimpleDefaultValues +{ + static T zero() { return static_cast<T>(0); } + static T one() { return static_cast<T>(1); } +}; + +// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. +template <class T> +struct NormalizedDefaultValues +{ + static T zero() { return static_cast<T>(0); } + static T one() { return std::numeric_limits<T>::max(); } +}; + +// Converter: +// static const bool identity: true if this is an identity transform (with no widening) +// static const std::size_t finalSize: number of bytes per output vertex +// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. + +template <class InT, + class WidenRule, + class Converter, + class DefaultValueRule = SimpleDefaultValues<InT>> +struct VertexDataConverter +{ + typedef typename Converter::OutputType OutputType; + typedef InT InputType; + + static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; + static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); + + static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output) + { + OutputType *out = reinterpret_cast<OutputType*>(output); + + for (std::size_t i = 0; i < n; i++) + { + const InputType *ein = reinterpret_cast<const InputType*>(input + i * stride); + + copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one())); + + out += WidenRule::finalWidth; + } + } + + private: + static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) + { + if (WidenRule::finalWidth > elementindex) + { + if (WidenRule::initialWidth > elementindex) + { + out[elementindex] = Converter::convert(in[elementindex]); + } + else + { + out[elementindex] = defaultvalue; + } + } + } +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ diff --git a/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h new file mode 100755 index 000000000..4893beb9a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h @@ -0,0 +1,41 @@ +// +// 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. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ +#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ + +#include "angle_gl.h" + +#include <cstddef> +#include <stdint.h> + +#include <map> + +namespace gl +{ +struct FormatType; +} + +namespace rx +{ +typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +enum VertexConversionType +{ + VERTEX_CONVERT_NONE = 0, + VERTEX_CONVERT_CPU = 1, + VERTEX_CONVERT_GPU = 2, + VERTEX_CONVERT_BOTH = 3 +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ |