diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2019-04-16 16:32:08 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2019-04-16 16:32:08 +0200 |
commit | 6630937e63ae5797487b86743a7733c8ae5cc42c (patch) | |
tree | 3d53dacf6430f9099e1fb20835881205de674961 /src/3rdparty/angle/src/libANGLE/renderer/d3d | |
parent | 37ed6dae00640f9cc980ffda05347c12a7eb5d7e (diff) | |
parent | c7af193d2e49e9f10b86262e63d8d13abf72b5cf (diff) |
Merge commit 'dev' into 'wip/cmake-merge'
Change-Id: I176c40d031be26a1dd1cf08843e448a660598783
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d')
204 files changed, 35474 insertions, 30972 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp index ffca99c3ac..7769ab2b75 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -12,42 +12,33 @@ #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(BufferFactoryD3D *factory) - : BufferImpl(), +BufferD3D::BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory) + : BufferImpl(state), mFactory(factory), - mStaticVertexBuffer(nullptr), mStaticIndexBuffer(nullptr), - mStaticBufferCache(nullptr), mStaticBufferCacheTotalSize(0), mStaticVertexBufferOutOfDate(false), mUnmodifiedDataUse(0), - mUsage(D3D_BUFFER_USAGE_STATIC) + mUsage(D3DBufferUsage::STATIC) { updateSerial(); } BufferD3D::~BufferD3D() { - SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticIndexBuffer); - - emptyStaticBufferCache(); } void BufferD3D::emptyStaticBufferCache() { - if (mStaticBufferCache != nullptr) - { - SafeDeleteContainer(*mStaticBufferCache); - SafeDelete(mStaticBufferCache); - } - + mStaticVertexBuffers.clear(); mStaticBufferCacheTotalSize = 0; } @@ -56,35 +47,37 @@ void BufferD3D::updateSerial() mSerial = mNextSerial++; } -void BufferD3D::updateD3DBufferUsage(GLenum usage) +void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage) { switch (usage) { - case GL_STATIC_DRAW: - case GL_STATIC_READ: - case GL_STATIC_COPY: - mUsage = D3D_BUFFER_USAGE_STATIC; - initializeStaticData(); + case gl::BufferUsage::StaticCopy: + case gl::BufferUsage::StaticDraw: + case gl::BufferUsage::StaticRead: + mUsage = D3DBufferUsage::STATIC; + initializeStaticData(context); 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 = D3D_BUFFER_USAGE_DYNAMIC; + case gl::BufferUsage::DynamicCopy: + case gl::BufferUsage::DynamicDraw: + case gl::BufferUsage::DynamicRead: + case gl::BufferUsage::StreamCopy: + case gl::BufferUsage::StreamDraw: + case gl::BufferUsage::StreamRead: + mUsage = D3DBufferUsage::DYNAMIC; break; default: UNREACHABLE(); } } -void BufferD3D::initializeStaticData() +void BufferD3D::initializeStaticData(const gl::Context *context) { - if (!mStaticVertexBuffer) + if (mStaticVertexBuffers.empty()) { - mStaticVertexBuffer = new StaticVertexBufferInterface(mFactory); + StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory); + mStaticVertexBuffers.push_back( + std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer)); } if (!mStaticIndexBuffer) { @@ -97,168 +90,101 @@ StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer() return mStaticIndexBuffer; } -StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer( - const gl::VertexAttribute &attribute, - D3DStaticBufferCreationType creationType) +StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute, + const gl::VertexBinding &binding) { - if (!mStaticVertexBuffer) + if (mStaticVertexBuffers.empty()) { // Early out if there aren't any static buffers at all - ASSERT(mStaticBufferCache == nullptr); return nullptr; } - if (mStaticBufferCache == nullptr && !mStaticVertexBuffer->isCommitted()) + // Early out, the attribute can be added to mStaticVertexBuffer. + if (mStaticVertexBuffers.size() == 1 && mStaticVertexBuffers[0]->empty()) { - // Early out, the attribute can be added to mStaticVertexBuffer or is already in there - return mStaticVertexBuffer; + return mStaticVertexBuffers[0].get(); } - // At this point, see if any of the existing static buffers contains the attribute data + // Cache size limiting: track the total allocated buffer sizes. + size_t currentTotalSize = 0; - // If the default static vertex buffer contains the attribute, then return it - if (mStaticVertexBuffer->lookupAttribute(attribute, nullptr)) - { - return mStaticVertexBuffer; - } - - if (mStaticBufferCache != nullptr) + // 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 there is a cached static buffer that already contains the attribute, then return it - for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache) + if (staticBuffer->matchesAttribute(attribute, binding)) { - if (staticBuffer->lookupAttribute(attribute, nullptr)) - { - return staticBuffer; - } + return staticBuffer.get(); } - } - if (!mStaticVertexBuffer->isCommitted()) - { - // None of the existing static buffers contain the attribute data and we are able to add - // the data to mStaticVertexBuffer, so we should just do so - return mStaticVertexBuffer; + currentTotalSize += staticBuffer->getBufferSize(); } - // At this point, we must create a new static buffer for the attribute data - if (creationType != D3D_BUFFER_CREATE_IF_NECESSARY) - { - return nullptr; - } + // 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)); - ASSERT(mStaticVertexBuffer); - ASSERT(mStaticVertexBuffer->isCommitted()); - unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize(); - if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize)) + // 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) { - // Ensure that the total size of the static buffer cache remains less than 4x the - // size of the original buffer - unsigned int maxStaticCacheSize = - IsUnsignedMultiplicationSafe(static_cast<unsigned int>(getSize()), 4u) - ? 4u * static_cast<unsigned int>(getSize()) - : std::numeric_limits<unsigned int>::max(); - - // We can't reuse the default static vertex buffer, so we add it to the cache - if (staticVertexBufferSize + mStaticBufferCacheTotalSize <= maxStaticCacheSize) - { - if (mStaticBufferCache == nullptr) - { - mStaticBufferCache = new std::vector<StaticVertexBufferInterface *>(); - } - - mStaticBufferCacheTotalSize += staticVertexBufferSize; - (*mStaticBufferCache).push_back(mStaticVertexBuffer); - mStaticVertexBuffer = nullptr; - - // Then reinitialize the static buffers to create a new static vertex buffer - initializeStaticData(); - - // Return the default static vertex buffer - return mStaticVertexBuffer; - } + emptyStaticBufferCache(); } - // At this point: - // - mStaticVertexBuffer is committed and can't be altered - // - mStaticBufferCache is full (or nearly overflowing) - // The inputted attribute should be put in some static buffer at some point, but it can't - // go in one right now, since mStaticBufferCache is full and we can't delete mStaticVertexBuffer - // in case another attribute is relying upon it for the current draw. - // We therefore mark mStaticVertexBuffer for deletion at the next possible time. - mStaticVertexBufferOutOfDate = true; - return nullptr; + // At this point, we must create a new static buffer for the attribute data. + StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory); + newStaticBuffer->setAttribute(attribute, binding); + mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer)); + return newStaticBuffer; } -void BufferD3D::reinitOutOfDateStaticData() +void BufferD3D::invalidateStaticData(const gl::Context *context) { - if (mStaticVertexBufferOutOfDate) - { - // During the last draw the caller tried to use some attribute with static data, but neither - // the static buffer cache nor mStaticVertexBuffer contained that data. - // Therefore, invalidate mStaticVertexBuffer so that if the caller tries to use that - // attribute in the next draw, it'll successfully get put into mStaticVertexBuffer. - invalidateStaticData(D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY); - mStaticVertexBufferOutOfDate = false; - } -} + emptyStaticBufferCache(); -void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType) -{ - if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr) + if (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0) { - emptyStaticBufferCache(); + SafeDelete(mStaticIndexBuffer); } - if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) + // 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) { - SafeDelete(mStaticVertexBuffer); - 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 == D3D_BUFFER_USAGE_STATIC) - { - initializeStaticData(); - } + initializeStaticData(context); } mUnmodifiedDataUse = 0; } // Creates static buffers if sufficient used data has been left unmodified -void BufferD3D::promoteStaticUsage(int dataSize) +void BufferD3D::promoteStaticUsage(const gl::Context *context, int dataSize) { - if (!mStaticVertexBuffer && !mStaticIndexBuffer) + if (mUsage == D3DBufferUsage::DYNAMIC) { - // There isn't any scenario that involves promoting static usage and the static buffer cache - // being non-empty - ASSERT(mStaticBufferCache == nullptr); - mUnmodifiedDataUse += dataSize; if (mUnmodifiedDataUse > 3 * getSize()) { - initializeStaticData(); + updateD3DBufferUsage(context, gl::BufferUsage::StaticDraw); } } } -gl::Error BufferD3D::getIndexRange(GLenum type, +gl::Error BufferD3D::getIndexRange(const gl::Context *context, + GLenum type, size_t offset, size_t count, bool primitiveRestartEnabled, gl::IndexRange *outRange) { const uint8_t *data = nullptr; - gl::Error error = getData(&data); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getData(context, &data)); *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h index a27ca9857a..60153748e6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -15,71 +15,69 @@ #include <stdint.h> #include <vector> +namespace gl +{ +struct VertexAttribute; +class VertexBinding; +} + namespace rx { class BufferFactoryD3D; class StaticIndexBufferInterface; class StaticVertexBufferInterface; -enum D3DBufferUsage -{ - D3D_BUFFER_USAGE_STATIC, - D3D_BUFFER_USAGE_DYNAMIC, -}; - -enum D3DBufferInvalidationType +enum class D3DBufferUsage { - D3D_BUFFER_INVALIDATE_WHOLE_CACHE, - D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY, -}; - -enum D3DStaticBufferCreationType -{ - D3D_BUFFER_CREATE_IF_NECESSARY, - D3D_BUFFER_DO_NOT_CREATE, + STATIC, + DYNAMIC, }; class BufferD3D : public BufferImpl { public: - BufferD3D(BufferFactoryD3D *factory); - virtual ~BufferD3D(); + BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory); + ~BufferD3D() override; unsigned int getSerial() const { return mSerial; } virtual size_t getSize() const = 0; virtual bool supportsDirectBinding() const = 0; - virtual void markTransformFeedbackUsage() = 0; - virtual gl::Error getData(const uint8_t **outData) = 0; + virtual gl::Error markTransformFeedbackUsage(const gl::Context *context) = 0; + virtual gl::Error getData(const gl::Context *context, const uint8_t **outData) = 0; + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute, - D3DStaticBufferCreationType creationType); + const gl::VertexBinding &binding); StaticIndexBufferInterface *getStaticIndexBuffer(); - void initializeStaticData(); - void invalidateStaticData(D3DBufferInvalidationType invalidationType); - void reinitOutOfDateStaticData(); + virtual void initializeStaticData(const gl::Context *context); + virtual void invalidateStaticData(const gl::Context *context); - void promoteStaticUsage(int dataSize); + void promoteStaticUsage(const gl::Context *context, int dataSize); - gl::Error getIndexRange(GLenum type, + gl::Error getIndexRange(const gl::Context *context, + 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 updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage); void emptyStaticBufferCache(); BufferFactoryD3D *mFactory; unsigned int mSerial; static unsigned int mNextSerial; - StaticVertexBufferInterface *mStaticVertexBuffer; + std::vector<std::unique_ptr<StaticVertexBufferInterface>> mStaticVertexBuffers; StaticIndexBufferInterface *mStaticIndexBuffer; - std::vector<StaticVertexBufferInterface *> *mStaticBufferCache; unsigned int mStaticBufferCacheTotalSize; unsigned int mStaticVertexBufferOutOfDate; unsigned int mUnmodifiedDataUse; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp index 6f8d1717cd..8ceeec3c39 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp @@ -17,4 +17,14 @@ CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType) { } +gl::Error CompilerD3D::release() +{ + return gl::NoError(); +} + +ShShaderOutput CompilerD3D::getTranslatorOutputType() const +{ + return mTranslatorOutputType; +} + } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h index 8f4334963d..bcfe810d04 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h @@ -21,8 +21,8 @@ class CompilerD3D : public CompilerImpl CompilerD3D(ShShaderOutput translatorOutputType); ~CompilerD3D() override {} - gl::Error release() override { return gl::Error(GL_NO_ERROR); } - ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; } + gl::Error release() override; + ShShaderOutput getTranslatorOutputType() const override; private: ShShaderOutput mTranslatorOutputType; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp index f40e6e6cab..5a06b15279 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp @@ -39,11 +39,11 @@ egl::Error DeviceD3D::getDevice(void **outValue) if (!mIsInitialized) { *outValue = nullptr; - return egl::Error(EGL_BAD_DEVICE_EXT); + return egl::EglBadDevice(); } *outValue = mDevice; - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } egl::Error DeviceD3D::initialize(void *device, @@ -53,15 +53,11 @@ egl::Error DeviceD3D::initialize(void *device, ASSERT(!mIsInitialized); if (mIsInitialized) { - return egl::Error(EGL_BAD_DEVICE_EXT); + return egl::EglBadDevice(); } - mDevice = device; - mDeviceType = deviceType; - mDeviceExternallySourced = !!deviceExternallySourced; - #if defined(ANGLE_ENABLE_D3D11) - if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + if (deviceType == EGL_D3D11_DEVICE_ANGLE) { // Validate the device IUnknown *iunknown = reinterpret_cast<IUnknown *>(device); @@ -71,7 +67,7 @@ egl::Error DeviceD3D::initialize(void *device, iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice)); if (FAILED(hr)) { - return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT"); + return egl::EglBadAttribute() << "Invalid D3D device passed into EGLDeviceEXT"; } // The QI to ID3D11Device adds a ref to the D3D11 device. @@ -81,12 +77,15 @@ egl::Error DeviceD3D::initialize(void *device, else #endif { - ASSERT(!mDeviceExternallySourced); + ASSERT(deviceExternallySourced == EGL_FALSE); } - mIsInitialized = true; + mDevice = device; + mDeviceType = deviceType; + mDeviceExternallySourced = !!deviceExternallySourced; + mIsInitialized = true; - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } EGLint DeviceD3D::getType() @@ -99,4 +98,8 @@ void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const outExtensions->deviceD3D = true; } +bool DeviceD3D::deviceExternallySourced() +{ + return mDeviceExternallySourced; +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h index 1dd9979708..15eaf9210a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h @@ -25,7 +25,7 @@ class DeviceD3D : public DeviceImpl egl::Error getDevice(void **outValue) override; EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; - bool deviceExternallySourced() override { return mDeviceExternallySourced; } + bool deviceExternallySourced() override; private: void *mDevice; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp index d4dc702582..0edda9c584 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -8,18 +8,19 @@ #include "libANGLE/renderer/d3d/DisplayD3D.h" -#include "libANGLE/Context.h" +#include <EGL/eglext.h> + #include "libANGLE/Config.h" +#include "libANGLE/Context.h" #include "libANGLE/Display.h" #include "libANGLE/Surface.h" +#include "libANGLE/Thread.h" #include "libANGLE/histogram_macros.h" +#include "libANGLE/renderer/d3d/DeviceD3D.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" - -#include <EGL/eglext.h> #if defined (ANGLE_ENABLE_D3D9) # include "libANGLE/renderer/d3d/d3d9/Renderer9.h" @@ -29,10 +30,6 @@ # include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #endif // ANGLE_ENABLE_D3D11 -#if defined (ANGLE_TEST_CONFIG) -# define ANGLE_DEFAULT_D3D11 1 -#endif - #if !defined(ANGLE_DEFAULT_D3D11) // Enables use of the Direct3D 11 API for a default display, when available # define ANGLE_DEFAULT_D3D11 1 @@ -60,8 +57,8 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) const auto &attribMap = display->getAttributeMap(); EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); - EGLint requestedDisplayType = - attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + 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 || @@ -117,11 +114,10 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) 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(); + egl::Error result = renderer->initialize(); # if defined(ANGLE_ENABLE_D3D11) if (renderer->getRendererClass() == RENDERER_D3D11) @@ -146,70 +142,45 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) if (!result.isError()) { *outRenderer = renderer; - break; - } - else - { - // Failed to create the renderer, try the next - SafeDelete(renderer); + return result; } + + // Failed to create the renderer, try the next + SafeDelete(renderer); } - return result; + return egl::EglNotInitialized() << "No available renderers."; } -DisplayD3D::DisplayD3D() : mRenderer(nullptr) +DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr) { } - -SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration, +SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state, EGLNativeWindowType window, const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); - - EGLint width = attribs.get(EGL_WIDTH, 0); - EGLint height = attribs.get(EGL_HEIGHT, 0); - EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE); - EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0); - EGLint directComposition = attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE); - - if (!fixedSize) - { - width = -1; - height = -1; - } - - return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, - directComposition, width, height, orientation); + return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs); } -SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration, +SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state, const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); - - EGLint width = attribs.get(EGL_WIDTH, 0); - EGLint height = attribs.get(EGL_HEIGHT, 0); - - return SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, nullptr, width, height); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs); } -SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, - EGLClientBuffer shareHandle, +SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state, + EGLenum buftype, + EGLClientBuffer clientBuffer, const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); - - EGLint width = attribs.get(EGL_WIDTH, 0); - EGLint height = attribs.get(EGL_HEIGHT, 0); - - return SurfaceD3D::createOffscreen( - mRenderer, mDisplay, configuration, shareHandle, width, height); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs); } -SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::Config *configuration, +SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state, NativePixmapType nativePixmap, const egl::AttributeMap &attribs) { @@ -217,11 +188,11 @@ SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::Config *configuration, return nullptr; } -ImageImpl *DisplayD3D::createImage(EGLenum target, - egl::ImageSibling *buffer, +ImageImpl *DisplayD3D::createImage(const egl::ImageState &state, + EGLenum target, const egl::AttributeMap &attribs) { - return new EGLImageD3D(mRenderer, target, buffer, attribs); + return new EGLImageD3D(state, target, attribs, mRenderer); } egl::Error DisplayD3D::getDevice(DeviceImpl **device) @@ -229,30 +200,31 @@ egl::Error DisplayD3D::getDevice(DeviceImpl **device) return mRenderer->getEGLDevice(device); } -gl::Context *DisplayD3D::createContext(const egl::Config *config, - const gl::Context *shareContext, - const egl::AttributeMap &attribs) +ContextImpl *DisplayD3D::createContext(const gl::ContextState &state) { ASSERT(mRenderer != nullptr); - return new gl::Context(config, shareContext, mRenderer, attribs); + 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); + return egl::NoError(); } egl::Error DisplayD3D::initialize(egl::Display *display) { ASSERT(mRenderer == nullptr && display != nullptr); mDisplay = display; - egl::Error error = CreateRendererD3D(display, &mRenderer); - if (error.isError()) - { - return error; - } - - return egl::Error(EGL_SUCCESS); + ANGLE_TRY(CreateRendererD3D(display, &mRenderer)); + return egl::NoError(); } void DisplayD3D::terminate() @@ -260,32 +232,26 @@ void DisplayD3D::terminate() SafeDelete(mRenderer); } -egl::ConfigSet DisplayD3D::generateConfigs() const +egl::ConfigSet DisplayD3D::generateConfigs() { ASSERT(mRenderer != nullptr); return mRenderer->generateConfigs(); } -bool DisplayD3D::isDeviceLost() const -{ - ASSERT(mRenderer != nullptr); - return mRenderer->isDeviceLost(); -} - bool DisplayD3D::testDeviceLost() { ASSERT(mRenderer != nullptr); return mRenderer->testDeviceLost(); } -egl::Error DisplayD3D::restoreLostDevice() +egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display) { // Release surface resources to make the Reset() succeed - for (auto &surface : mSurfaceSet) + for (egl::Surface *surface : mState.surfaceSet) { if (surface->getBoundTexture()) { - surface->releaseTexImage(EGL_BACK_BUFFER); + ANGLE_TRY(surface->releaseTexImage(display->getProxyContext(), EGL_BACK_BUFFER)); } SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); surfaceD3D->releaseSwapChain(); @@ -293,27 +259,43 @@ egl::Error DisplayD3D::restoreLostDevice() if (!mRenderer->resetDevice()) { - return egl::Error(EGL_BAD_ALLOC); + return egl::EglBadAlloc(); } // Restore any surfaces that may have been lost - for (const auto &surface : mSurfaceSet) + for (const egl::Surface *surface : mState.surfaceSet) { SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); - egl::Error error = surfaceD3D->resetSwapChain(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(surfaceD3D->resetSwapChain(display)); } - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const { - return NativeWindow::isValidNativeWindow(window); + 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( + configuration, static_cast<IUnknown *>(clientBuffer), nullptr, nullptr, nullptr); + + default: + return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs); + } } void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const @@ -337,20 +319,43 @@ void DisplayD3D::generateCaps(egl::Caps *outCaps) const // Display must be initialized to generate caps ASSERT(mRenderer != nullptr); - outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT; + outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT; } -egl::Error DisplayD3D::waitClient() const +egl::Error DisplayD3D::waitClient(const gl::Context *context) const { - // Unimplemented as it is a noop on D3D - return egl::Error(EGL_SUCCESS); + for (egl::Surface *surface : mState.surfaceSet) + { + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(context)); + } + + return egl::NoError(); } -egl::Error DisplayD3D::waitNative(EGLint engine, - egl::Surface *drawSurface, - egl::Surface *readSurface) const +egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine) const { - // Unimplemented as it is a noop on D3D - return egl::Error(EGL_SUCCESS); + egl::Surface *drawSurface = context->getCurrentDrawSurface(); + egl::Surface *readSurface = context->getCurrentReadSurface(); + + if (drawSurface != nullptr) + { + SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface); + ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(context)); + } + + if (readSurface != nullptr) + { + SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface); + ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(context)); + } + + return egl::NoError(); } + +gl::Version DisplayD3D::getMaxSupportedESVersion() const +{ + return mRenderer->getMaxSupportedESVersion(); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h index 0ce196dea2..7090522312 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -19,50 +19,55 @@ class RendererD3D; class DisplayD3D : public DisplayImpl { public: - DisplayD3D(); + DisplayD3D(const egl::DisplayState &state); egl::Error initialize(egl::Display *display) override; - virtual void terminate() override; + void terminate() override; // Surface creation - SurfaceImpl *createWindowSurface(const egl::Config *configuration, + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, EGLNativeWindowType window, const egl::AttributeMap &attribs) override; - SurfaceImpl *createPbufferSurface(const egl::Config *configuration, + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, const egl::AttributeMap &attribs) override; - SurfaceImpl *createPbufferFromClientBuffer(const egl::Config *configuration, - EGLClientBuffer shareHandle, + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + EGLenum buftype, + EGLClientBuffer clientBuffer, const egl::AttributeMap &attribs) override; - SurfaceImpl *createPixmapSurface(const egl::Config *configuration, + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, NativePixmapType nativePixmap, const egl::AttributeMap &attribs) override; - ImageImpl *createImage(EGLenum target, - egl::ImageSibling *buffer, + ImageImpl *createImage(const egl::ImageState &state, + EGLenum target, const egl::AttributeMap &attribs) override; - gl::Context *createContext(const egl::Config *config, - const gl::Context *shareContext, - 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() const override; + egl::ConfigSet generateConfigs() override; - bool isDeviceLost() const override; bool testDeviceLost() override; - egl::Error restoreLostDevice() override; + egl::Error restoreLostDevice(const egl::Display *display) 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; + egl::Error waitClient(const gl::Context *context) const override; + egl::Error waitNative(const gl::Context *context, EGLint engine) const override; + gl::Version getMaxSupportedESVersion() const override; private: void generateExtensions(egl::DisplayExtensions *outExtensions) const override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index 42a534f573..b4143a3f5f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -8,15 +8,17 @@ #include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "common/string_utils.h" #include "common/utilities.h" #include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/Context.h" #include "libANGLE/Program.h" #include "libANGLE/Shader.h" +#include "libANGLE/VaryingPacking.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; @@ -26,7 +28,28 @@ namespace rx namespace { -std::string HLSLComponentTypeString(GLenum componentType) +// This class needs to match OutputHLSL::decorate +class DecorateVariable final : angle::NonCopyable +{ + public: + explicit DecorateVariable(const std::string &str) : mName(str) {} + const std::string &getName() const { return mName; } + + private: + const std::string &mName; +}; + +std::ostream &operator<<(std::ostream &o, const DecorateVariable &dv) +{ + if (dv.getName().compare(0, 3, "gl_") != 0) + { + o << "_"; + } + o << dv.getName(); + return o; +} + +const char *HLSLComponentTypeString(GLenum componentType) { switch (componentType) { @@ -44,12 +67,16 @@ std::string HLSLComponentTypeString(GLenum componentType) } } -std::string HLSLComponentTypeString(GLenum componentType, int componentCount) +void HLSLComponentTypeString(std::ostringstream &ostream, GLenum componentType, int componentCount) { - return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : ""); + ostream << HLSLComponentTypeString(componentType); + if (componentCount > 1) + { + ostream << componentCount; + } } -std::string HLSLMatrixTypeString(GLenum type) +const char *HLSLMatrixTypeString(GLenum type) { switch (type) { @@ -77,15 +104,16 @@ std::string HLSLMatrixTypeString(GLenum type) } } -std::string HLSLTypeString(GLenum type) +void HLSLTypeString(std::ostringstream &ostream, GLenum type) { if (gl::IsMatrixType(type)) { - return HLSLMatrixTypeString(type); + ostream << HLSLMatrixTypeString(type); + return; } - return HLSLComponentTypeString(gl::VariableComponentType(type), - gl::VariableComponentCount(type)); + HLSLComponentTypeString(ostream, gl::VariableComponentType(type), + gl::VariableComponentCount(type)); } const PixelShaderOutputVariable *FindOutputAtLocation( @@ -103,7 +131,7 @@ const PixelShaderOutputVariable *FindOutputAtLocation( return nullptr; } -void WriteArrayString(std::stringstream &strstr, unsigned int i) +void WriteArrayString(std::ostringstream &strstr, unsigned int i) { static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int."); @@ -117,16 +145,14 @@ void WriteArrayString(std::stringstream &strstr, unsigned int i) strstr << "]"; } -const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; -const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; +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"); -} +// BuiltinInfo implementation + +BuiltinInfo::BuiltinInfo() = default; +BuiltinInfo::~BuiltinInfo() = default; // DynamicHLSL implementation @@ -134,55 +160,13 @@ 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; + std::ostringstream structStream; + std::ostringstream initStream; structStream << "struct VS_INPUT\n" << "{\n"; @@ -231,26 +215,31 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout( { GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType); - if (shaderAttribute.name == "gl_InstanceID") + if (shaderAttribute.name == "gl_InstanceID" || + shaderAttribute.name == "gl_VertexID") { - // The input type of the instance ID in HLSL (uint) differs from the one in ESSL - // (int). + // 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 << " "; + HLSLComponentTypeString(structStream, componentType, + VariableComponentCount(shaderAttribute.type)); } } - structStream << " " << decorateVariable(shaderAttribute.name) << " : "; + 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; @@ -260,7 +249,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout( structStream << ";\n"; // HLSL code for initialization - initStream << " " << decorateVariable(shaderAttribute.name) << " = "; + 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) @@ -268,11 +257,11 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout( if (IsMatrixType(shaderAttribute.type) || (mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0) { - initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute); + GenerateAttributeConversionHLSL(vertexFormatType, shaderAttribute, initStream); } else { - initStream << "input." << decorateVariable(shaderAttribute.name); + initStream << "input." << DecorateVariable(shaderAttribute.name); } initStream << ";\n"; @@ -289,8 +278,9 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout( std::string vertexHLSL(sourceShader); - size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); - vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str()); + bool success = + angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str()); + ASSERT(success); return vertexHLSL; } @@ -305,22 +295,32 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; - std::stringstream declarationStream; - std::stringstream copyStream; + std::ostringstream declarationStream; + std::ostringstream copyStream; declarationStream << "struct PS_OUTPUT\n" "{\n"; - for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) + size_t numOutputs = outputLayout.size(); + + // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain. + if (numOutputs == 0 && (shaderModel == 3 || !mRenderer->getShaderModelSuffix().empty())) + { + numOutputs = 1u; + } + const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "dummy", "float4(0, 0, 0, 1)", 0); + + for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex) { - GLenum binding = outputLayout[layoutIndex]; + GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex]; if (binding != GL_NONE) { unsigned int location = (binding - GL_COLOR_ATTACHMENT0); const PixelShaderOutputVariable *outputVariable = - FindOutputAtLocation(outputVariables, location); + outputLayout.empty() ? &defaultOutput + : FindOutputAtLocation(outputVariables, location); // OpenGL ES 3.0 spec $4.2.1 // If [...] not all user-defined output variables are written, the values of fragment @@ -328,8 +328,9 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( // corresponding to unwritten variables are similarly undefined. if (outputVariable) { - declarationStream << " " + HLSLTypeString(outputVariable->type) << " " - << outputVariable->name << " : " << targetSemantic + declarationStream << " "; + HLSLTypeString(declarationStream, outputVariable->type); + declarationStream << " " << outputVariable->name << " : " << targetSemantic << static_cast<int>(layoutIndex) << ";\n"; copyStream << " output." << outputVariable->name << " = " @@ -354,61 +355,113 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( std::string pixelHLSL(sourceShader); - size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); - pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), - declarationStream.str()); + bool success = + angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str()); + ASSERT(success); return pixelHLSL; } -void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType, - const VaryingPacking &varyingPacking, - std::stringstream &linkStream) const +void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking, + const BuiltinInfo &builtins, + bool programUsesPointSize, + std::ostringstream &hlslStream) const { - const auto &builtins = varyingPacking.builtins(shaderType); ASSERT(builtins.dxPosition.enabled); - linkStream << "{\n" + hlslStream << "{\n" << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; if (builtins.glPosition.enabled) { - linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; + hlslStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; } if (builtins.glFragCoord.enabled) { - linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; + hlslStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; } if (builtins.glPointCoord.enabled) { - linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; + hlslStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; } if (builtins.glPointSize.enabled) { - linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; + hlslStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; + } + + if (builtins.glViewIDOVR.enabled) + { + hlslStream << " nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str() + << ";\n"; + } + + if (builtins.glViewportIndex.enabled) + { + hlslStream << " nointerpolation uint gl_ViewportIndex : " + << builtins.glViewportIndex.str() << ";\n"; + } + + if (builtins.glLayer.enabled) + { + hlslStream << " nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n"; } - // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the - // same register. - generateVaryingHLSL(varyingPacking, linkStream); + std::string varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize); - linkStream << "};\n"; + 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); + HLSLComponentTypeString(hlslStream, componentType, columnCount); + unsigned int semanticIndex = registerInfo.semanticIndex; + hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n"; + } + + hlslStream << "};\n"; } -bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, - const gl::Program::Data &programData, +void DynamicHLSL::generateShaderLinkHLSL(const gl::Context *context, + const gl::ProgramState &programData, const ProgramD3DMetadata &programMetadata, const VaryingPacking &varyingPacking, + const BuiltinVaryingsD3D &builtinsD3D, std::string *pixelHLSL, std::string *vertexHLSL) const { ASSERT(pixelHLSL->empty() && vertexHLSL->empty()); - const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader(); - const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(vertexShaderGL); - const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader(); + const auto &data = context->getContextState(); + gl::Shader *vertexShaderGL = programData.getAttachedVertexShader(); + gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader(); const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL); const int shaderModel = mRenderer->getMajorShaderModel(); @@ -422,48 +475,59 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, // Validation done in the compiler ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); - std::stringstream vertexStream; - vertexStream << vertexShaderGL->getTranslatedSource(); + std::ostringstream vertexStream; + vertexStream << vertexShaderGL->getTranslatedSource(context); // 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.caps->minAliasedPointSize) << ".0f;\n" + << static_cast<int>(data.getCaps().minAliasedPointSize) << ".0f;\n" << "static float maxPointSize = " - << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n"; + << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n"; } // Add stub string to be replaced when shader is dynamically defined by its layout - vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n"; + vertexStream << "\n" << std::string(VERTEX_ATTRIBUTE_STUB_STRING) << "\n"; + + const auto &vertexBuiltins = builtinsD3D[gl::SHADER_VERTEX]; // Write the HLSL input/output declarations vertexStream << "struct VS_OUTPUT\n"; - generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream); + generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), + vertexStream); vertexStream << "\n" << "VS_OUTPUT main(VS_INPUT input)\n" << "{\n" << " initAttributes(input);\n"; - if (vertexShader->usesDeferredInit()) - { - vertexStream << "\n" - << " initializeDeferredGlobals();\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"; } + if (vertexBuiltins.glViewIDOVR.enabled) + { + vertexStream << " output.gl_ViewID_OVR = _ViewID_OVR;\n"; + } + if (programMetadata.hasANGLEMultiviewEnabled() && programMetadata.canSelectViewInVertexShader()) + { + ASSERT(vertexBuiltins.glViewportIndex.enabled && vertexBuiltins.glLayer.enabled); + vertexStream << " if (multiviewSelectViewportIndex)\n" + << " {\n" + << " output.gl_ViewportIndex = _ViewID_OVR;\n" + << " } else {\n" + << " output.gl_ViewportIndex = 0;\n" + << " output.gl_Layer = _ViewID_OVR;\n" + << " }\n"; + } + // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { @@ -528,10 +592,10 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, if (packedVarying.isStructField()) { - vertexStream << decorateVariable(packedVarying.parentStructName) << "."; + vertexStream << DecorateVariable(packedVarying.parentStructName) << "."; } - vertexStream << decorateVariable(varying.name); + vertexStream << DecorateVariable(varying.name); if (varying.isArray()) { @@ -593,13 +657,16 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, << " return output;\n" << "}\n"; - std::stringstream pixelStream; - pixelStream << fragmentShaderGL->getTranslatedSource(); + const auto &pixelBuiltins = builtinsD3D[gl::SHADER_FRAGMENT]; + + std::ostringstream pixelStream; + pixelStream << fragmentShaderGL->getTranslatedSource(context); pixelStream << "struct PS_INPUT\n"; - generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream); + generateVaryingLinkHLSL(varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(), + pixelStream); pixelStream << "\n"; - pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n"; + pixelStream << std::string(PIXEL_OUTPUT_STUB_STRING) << "\n"; if (fragmentShader->usesFrontFacing()) { @@ -620,7 +687,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, << "{\n"; } - const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL); + if (fragmentShader->usesViewID()) + { + ASSERT(pixelBuiltins.glViewIDOVR.enabled); + pixelStream << " _ViewID_OVR = input.gl_ViewID_OVR;\n"; + } if (pixelBuiltins.glFragCoord.enabled) { @@ -721,18 +792,19 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, const auto &varying = *packedVarying.varying; ASSERT(!varying.isBuiltIn() && !varying.isStruct()); - // Don't reference VS-only transform feedback varyings in the PS. - if (registerInfo.packedVarying->vertexOnly) + // Don't reference VS-only transform feedback varyings in the PS. Note that we're relying on + // that the staticUse flag is set according to usage in the fragment shader. + if (packedVarying.vertexOnly || !varying.staticUse) continue; pixelStream << " "; if (packedVarying.isStructField()) { - pixelStream << decorateVariable(packedVarying.parentStructName) << "."; + pixelStream << DecorateVariable(packedVarying.parentStructName) << "."; } - pixelStream << decorateVariable(varying.name); + pixelStream << DecorateVariable(varying.name); if (varying.isArray()) { @@ -766,12 +838,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, pixelStream << ";\n"; } - if (fragmentShader->usesDeferredInit()) - { - pixelStream << "\n" - << " initializeDeferredGlobals();\n"; - } - pixelStream << "\n" << " gl_main();\n" << "\n" @@ -780,34 +846,126 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, *vertexHLSL = vertexStream.str(); *pixelHLSL = pixelStream.str(); +} + +std::string DynamicHLSL::generateComputeShaderLinkHLSL(const gl::Context *context, + const gl::ProgramState &programData) const +{ + gl::Shader *computeShaderGL = programData.getAttachedComputeShader(); + std::stringstream computeStream; + std::string translatedSource = computeShaderGL->getTranslatedSource(context); + computeStream << translatedSource; + + bool usesWorkGroupID = translatedSource.find("GL_USES_WORK_GROUP_ID") != std::string::npos; + bool usesLocalInvocationID = + translatedSource.find("GL_USES_LOCAL_INVOCATION_ID") != std::string::npos; + bool usesGlobalInvocationID = + translatedSource.find("GL_USES_GLOBAL_INVOCATION_ID") != std::string::npos; + bool usesLocalInvocationIndex = + translatedSource.find("GL_USES_LOCAL_INVOCATION_INDEX") != std::string::npos; + + computeStream << "\nstruct CS_INPUT\n{\n"; + if (usesWorkGroupID) + { + computeStream << " uint3 dx_WorkGroupID : " + << "SV_GroupID;\n"; + } - return true; + if (usesLocalInvocationID) + { + computeStream << " uint3 dx_LocalInvocationID : " + << "SV_GroupThreadID;\n"; + } + + if (usesGlobalInvocationID) + { + computeStream << " uint3 dx_GlobalInvocationID : " + << "SV_DispatchThreadID;\n"; + } + + if (usesLocalInvocationIndex) + { + computeStream << " uint dx_LocalInvocationIndex : " + << "SV_GroupIndex;\n"; + } + + computeStream << "};\n\n"; + + const sh::WorkGroupSize &localSize = computeShaderGL->getWorkGroupSize(context); + computeStream << "[numthreads(" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] + << ")]\n"; + + computeStream << "void main(CS_INPUT input)\n" + << "{\n"; + + if (usesWorkGroupID) + { + computeStream << " gl_WorkGroupID = input.dx_WorkGroupID;\n"; + } + if (usesLocalInvocationID) + { + computeStream << " gl_LocalInvocationID = input.dx_LocalInvocationID;\n"; + } + if (usesGlobalInvocationID) + { + computeStream << " gl_GlobalInvocationID = input.dx_GlobalInvocationID;\n"; + } + if (usesLocalInvocationIndex) + { + computeStream << " gl_LocalInvocationIndex = input.dx_LocalInvocationIndex;\n"; + } + + computeStream << "\n" + << " gl_main();\n" + << "}\n"; + + return computeStream.str(); } -std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const +std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking, + const BuiltinVaryingsD3D &builtinsD3D, + const bool hasANGLEMultiviewEnabled, + const bool selectViewInVS) const { ASSERT(mRenderer->getMajorShaderModel() >= 4); - std::stringstream preambleStream; + std::ostringstream preambleStream; - const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + const auto &vertexBuiltins = builtinsD3D[gl::SHADER_VERTEX]; preambleStream << "struct GS_INPUT\n"; - generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream); + generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), + preambleStream); preambleStream << "\n" << "struct GS_OUTPUT\n"; - generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream); + generateVaryingLinkHLSL(varyingPacking, builtinsD3D[gl::SHADER_GEOMETRY], + builtinsD3D.usesPointSize(), 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) + if (vertexBuiltins.glPointSize.enabled) { preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; } + if (hasANGLEMultiviewEnabled) + { + preambleStream << " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n"; + if (selectViewInVS) + { + ASSERT(builtinsD3D[gl::SHADER_GEOMETRY].glViewportIndex.enabled && + builtinsD3D[gl::SHADER_GEOMETRY].glLayer.enabled); + + // If the view is already selected in the VS, then we just pass the gl_ViewportIndex and + // gl_Layer to the output. + preambleStream << " output.gl_ViewportIndex = input.gl_ViewportIndex;\n" + << " output.gl_Layer = input.gl_Layer;\n"; + } + } + for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList()) { preambleStream << " output.v" << varyingRegister.semanticIndex << " = "; @@ -818,7 +976,7 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n"; } - if (builtins.glFragCoord.enabled) + if (vertexBuiltins.glFragCoord.enabled) { preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; } @@ -829,20 +987,46 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va << "#endif // ANGLE_POINT_SPRITE_SHADER\n" << "}\n"; + if (hasANGLEMultiviewEnabled && !selectViewInVS) + { + ASSERT(builtinsD3D[gl::SHADER_GEOMETRY].glViewportIndex.enabled && + builtinsD3D[gl::SHADER_GEOMETRY].glLayer.enabled); + + // According to the HLSL reference, using SV_RenderTargetArrayIndex is only valid if the + // render target is an array resource. Because of this we do not write to gl_Layer if we are + // taking the side-by-side code path. We still select the viewport index in the layered code + // path as that is always valid. See: + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx + preambleStream << "\n" + << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n" + << "{\n" + << " if (multiviewSelectViewportIndex)\n" + << " {\n" + << " output.gl_ViewportIndex = input.gl_ViewID_OVR;\n" + << " } else {\n" + << " output.gl_ViewportIndex = 0;\n" + << " output.gl_Layer = input.gl_ViewID_OVR;\n" + << " }\n" + << "}\n"; + } + return preambleStream.str(); } -std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, - const gl::Data &data, - const gl::Program::Data &programData, +std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Context *context, + gl::PrimitiveType primitiveType, + const gl::ProgramState &programData, const bool useViewScale, + const bool hasANGLEMultiviewEnabled, + const bool selectViewInVS, + const bool pointSpriteEmulation, const std::string &preambleString) const { ASSERT(mRenderer->getMajorShaderModel() >= 4); std::stringstream shaderStream; - const bool pointSprites = (primitiveType == PRIMITIVE_POINTS); + const bool pointSprites = (primitiveType == PRIMITIVE_POINTS) && pointSpriteEmulation; const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos; const char *inputPT = nullptr; @@ -854,9 +1038,19 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT { case PRIMITIVE_POINTS: inputPT = "point"; - outputPT = "Triangle"; inputSize = 1; - maxVertexOutput = 4; + + if (pointSprites) + { + outputPT = "Triangle"; + maxVertexOutput = 4; + } + else + { + outputPT = "Point"; + maxVertexOutput = 1; + } + break; case PRIMITIVE_LINES: @@ -882,18 +1076,34 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT break; } - if (pointSprites) + if (pointSprites || hasANGLEMultiviewEnabled) { - shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" - "\n" - "uniform float4 dx_ViewCoords : register(c1);\n"; + shaderStream << "cbuffer DriverConstants : register(b0)\n" + "{\n"; + + if (pointSprites) + { + shaderStream << " float4 dx_ViewCoords : packoffset(c1);\n"; + if (useViewScale) + { + shaderStream << " float2 dx_ViewScale : packoffset(c3);\n"; + } + } - if (useViewScale) + if (hasANGLEMultiviewEnabled) { - shaderStream << "uniform float2 dx_ViewScale : register(c3);\n"; + // We have to add a value which we can use to keep track of which multi-view code path + // is to be selected in the GS. + shaderStream << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; } - shaderStream << "\n" + shaderStream << "};\n\n"; + } + + if (pointSprites) + { + shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" + "\n" "static float2 pointSpriteCorners[] = \n" "{\n" " float2( 0.5f, -0.5f),\n" @@ -911,10 +1121,10 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT "};\n" "\n" "static float minPointSize = " - << static_cast<int>(data.caps->minAliasedPointSize) + << static_cast<int>(context->getCaps().minAliasedPointSize) << ".0f;\n" "static float maxPointSize = " - << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n" + << static_cast<int>(context->getCaps().maxAliasedPointSize) << ".0f;\n" << "\n"; } @@ -944,7 +1154,10 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT { shaderStream << " copyVertex(output, input[" << vertexIndex << "], input[lastVertexIndex]);\n"; - + if (hasANGLEMultiviewEnabled && !selectViewInVS) + { + shaderStream << " selectView(output, input[" << vertexIndex << "]);\n"; + } if (!pointSprites) { ASSERT(inputSize == maxVertexOutput); @@ -995,50 +1208,38 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT 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 +// static +void DynamicHLSL::GenerateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib, + std::ostringstream &outStream) { - const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); - std::string attribString = "input." + decorateVariable(shaderAttrib.name); - // Matrix if (IsMatrixType(shaderAttrib.type)) { - return "transpose(" + attribString + ")"; + outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")"; + return; } GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); int shaderComponentCount = VariableComponentCount(shaderAttrib.type); + const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); // Perform integer to float conversion (if necessary) - bool requiresTypeConversion = - (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT); - - if (requiresTypeConversion) + if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT) { // TODO: normalization for 32-bit integer formats ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger); - return "float" + Str(shaderComponentCount) + "(" + attribString + ")"; + outStream << "float" << shaderComponentCount << "(input." + << DecorateVariable(shaderAttrib.name) << ")"; + return; } // No conversion necessary - return attribString; + outStream << "input." << DecorateVariable(shaderAttrib.name); } -void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data, - const gl::Program::Data &programData, +void DynamicHLSL::getPixelShaderOutputKey(const gl::ContextState &data, + const gl::ProgramState &programData, const ProgramD3DMetadata &metadata, std::vector<PixelShaderOutputVariable> *outPixelShaderKey) { @@ -1047,7 +1248,7 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data, // - 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.caps->maxDrawBuffers : 1); + (broadcast || metadata.usesMultipleFragmentOuts() ? data.getCaps().maxDrawBuffers : 1); if (metadata.getMajorShaderVersion() < 300) { @@ -1069,25 +1270,158 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data, const auto &shaderOutputVars = metadata.getFragmentShader()->getData().getActiveOutputVariables(); - for (auto outputPair : programData.getOutputVariables()) + for (size_t outputLocationIndex = 0u; + outputLocationIndex < programData.getOutputLocations().size(); ++outputLocationIndex) { - const VariableLocation &outputLocation = outputPair.second; + const VariableLocation &outputLocation = + programData.getOutputLocations().at(outputLocationIndex); + if (!outputLocation.used()) + { + continue; + } const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; - const std::string &variableName = "out_" + outputLocation.name; + const std::string &variableName = "out_" + outputVariable.name; + + // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6. const std::string &elementString = - (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); + (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : ""); ASSERT(outputVariable.staticUse); PixelShaderOutputVariable outputKeyVariable; outputKeyVariable.type = outputVariable.type; outputKeyVariable.name = variableName + elementString; - outputKeyVariable.source = variableName + ArrayString(outputLocation.element); - outputKeyVariable.outputIndex = outputPair.first; + outputKeyVariable.source = + variableName + + (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : ""); + outputKeyVariable.outputIndex = outputLocationIndex; outPixelShaderKey->push_back(outputKeyVariable); } } } +// BuiltinVarying Implementation. +BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false) +{ +} + +std::string BuiltinVarying::str() const +{ + return (systemValue ? semantic : (semantic + Str(index))); +} + +void BuiltinVarying::enableSystem(const std::string &systemValueSemantic) +{ + enabled = true; + semantic = systemValueSemantic; + systemValue = true; +} + +void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal) +{ + enabled = true; + semantic = semanticVal; + index = indexVal; +} + +// BuiltinVaryingsD3D Implementation. +BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, + const VaryingPacking &packing) +{ + updateBuiltins(gl::SHADER_VERTEX, metadata, packing); + updateBuiltins(gl::SHADER_FRAGMENT, metadata, packing); + if (metadata.getRendererMajorShaderModel() >= 4) + { + updateBuiltins(gl::SHADER_GEOMETRY, metadata, packing); + } +} + +BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default; + +void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType, + const ProgramD3DMetadata &metadata, + const VaryingPacking &packing) +{ + const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(), + metadata.usesSystemValuePointSize()); + + unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex(); + + BuiltinInfo *builtins = &mBuiltinInfo[shaderType]; + + if (metadata.getRendererMajorShaderModel() >= 4) + { + builtins->dxPosition.enableSystem("SV_Position"); + } + else if (shaderType == gl::SHADER_FRAGMENT) + { + builtins->dxPosition.enableSystem("VPOS"); + } + else + { + builtins->dxPosition.enableSystem("POSITION"); + } + + if (metadata.usesTransformFeedbackGLPosition()) + { + builtins->glPosition.enable(userSemantic, reservedSemanticIndex++); + } + + if (metadata.usesFragCoord()) + { + builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++); + } + + if (shaderType == gl::SHADER_VERTEX ? metadata.addsPointCoordToVertexShader() + : metadata.usesPointCoord()) + { + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + if (metadata.getRendererMajorShaderModel() >= 4) + { + builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++); + } + else + { + builtins->glPointCoord.enable("TEXCOORD", 0); + } + } + + if (shaderType == gl::SHADER_VERTEX && metadata.hasANGLEMultiviewEnabled()) + { + builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++); + if (metadata.canSelectViewInVertexShader()) + { + builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex"); + builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex"); + } + } + + if (shaderType == gl::SHADER_FRAGMENT && metadata.hasANGLEMultiviewEnabled()) + { + builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++); + } + + if (shaderType == gl::SHADER_GEOMETRY && metadata.hasANGLEMultiviewEnabled()) + { + // Although it is possible to retrieve gl_ViewID_OVR from the value of + // SV_ViewportArrayIndex or SV_RenderTargetArrayIndex based on the multi-view state in the + // driver constant buffer, it is easier and cleaner to pass it as a varying. + builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++); + + // gl_Layer and gl_ViewportIndex are necessary so that we can write to either based on the + // multiview state in the driver constant buffer. + builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex"); + builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex"); + } + + // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders + if (metadata.usesSystemValuePointSize() && + (shaderType != gl::SHADER_FRAGMENT || metadata.getRendererMajorShaderModel() >= 4)) + { + builtins->glPointSize.enableSystem("PSIZE"); + } +} + } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h index 69d941c06a..fe8d9cb0a3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -16,6 +16,7 @@ #include "common/angleutils.h" #include "libANGLE/Constants.h" #include "libANGLE/Program.h" +#include "libANGLE/angletypes.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/RendererD3D.h" @@ -29,23 +30,88 @@ namespace gl { class InfoLog; struct VariableLocation; +class VaryingPacking; struct VertexAttribute; -struct Data; } namespace rx { -struct PackedVarying; class ProgramD3DMetadata; class ShaderD3D; -class VaryingPacking; struct PixelShaderOutputVariable { - GLenum type; + PixelShaderOutputVariable() {} + PixelShaderOutputVariable(GLenum typeIn, + const std::string &nameIn, + const std::string &sourceIn, + size_t outputIndexIn) + : type(typeIn), name(nameIn), source(sourceIn), outputIndex(outputIndexIn) + { + } + + GLenum type = GL_NONE; std::string name; std::string source; - size_t outputIndex; + size_t outputIndex = 0; +}; + +struct BuiltinVarying final : private 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 +{ + BuiltinInfo(); + ~BuiltinInfo(); + + BuiltinVarying dxPosition; + BuiltinVarying glPosition; + BuiltinVarying glFragCoord; + BuiltinVarying glPointCoord; + BuiltinVarying glPointSize; + BuiltinVarying glViewIDOVR; + BuiltinVarying glViewportIndex; + BuiltinVarying glLayer; +}; + +inline 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"); +} + +class BuiltinVaryingsD3D +{ + public: + BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, const gl::VaryingPacking &packing); + ~BuiltinVaryingsD3D(); + + bool usesPointSize() const { return mBuiltinInfo[gl::SHADER_VERTEX].glPointSize.enabled; } + + const BuiltinInfo &operator[](gl::ShaderType shaderType) const + { + return mBuiltinInfo[shaderType]; + } + BuiltinInfo &operator[](gl::ShaderType shaderType) { return mBuiltinInfo[shaderType]; } + + private: + void updateBuiltins(gl::ShaderType shaderType, + const ProgramD3DMetadata &metadata, + const gl::VaryingPacking &packing); + + std::array<BuiltinInfo, gl::SHADER_TYPE_MAX> mBuiltinInfo; }; class DynamicHLSL : angle::NonCopyable @@ -62,43 +128,48 @@ class DynamicHLSL : angle::NonCopyable const std::vector<PixelShaderOutputVariable> &outputVariables, bool usesFragDepth, const std::vector<GLenum> &outputLayout) const; - bool generateShaderLinkHLSL(const gl::Data &data, - const gl::Program::Data &programData, + void generateShaderLinkHLSL(const gl::Context *context, + const gl::ProgramState &programData, const ProgramD3DMetadata &programMetadata, - const VaryingPacking &varyingPacking, + const gl::VaryingPacking &varyingPacking, + const BuiltinVaryingsD3D &builtinsD3D, std::string *pixelHLSL, std::string *vertexHLSL) const; + std::string generateComputeShaderLinkHLSL(const gl::Context *context, + const gl::ProgramState &programData) const; - std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const; + std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking, + const BuiltinVaryingsD3D &builtinsD3D, + const bool hasANGLEMultiviewEnabled, + const bool selectViewInVS) const; - std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, - const gl::Data &data, - const gl::Program::Data &programData, + std::string generateGeometryShaderHLSL(const gl::Context *context, + gl::PrimitiveType primitiveType, + const gl::ProgramState &programData, const bool useViewScale, + const bool hasANGLEMultiviewEnabled, + const bool selectViewInVS, + const bool pointSpriteEmulation, const std::string &preambleString) const; - void getPixelShaderOutputKey(const gl::Data &data, - const gl::Program::Data &programData, + 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); + void generateVaryingLinkHLSL(const gl::VaryingPacking &varyingPacking, + const BuiltinInfo &builtins, + bool programUsesPointSize, + std::ostringstream &hlslStream) const; - std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, - const sh::ShaderVariable &shaderAttrib) const; + static void GenerateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib, + std::ostringstream &outStream); }; -std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize); -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp index ca4b16987f..fcc2456bd6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp @@ -22,46 +22,14 @@ 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, +EGLImageD3D::EGLImageD3D(const egl::ImageState &state, EGLenum target, - egl::ImageSibling *buffer, - const egl::AttributeMap &attribs) - : mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr) + const egl::AttributeMap &attribs, + RendererD3D *renderer) + : ImageImpl(state), mRenderer(renderer), 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() @@ -71,62 +39,49 @@ EGLImageD3D::~EGLImageD3D() egl::Error EGLImageD3D::initialize() { - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling) +gl::Error EGLImageD3D::orphan(const gl::Context *context, egl::ImageSibling *sibling) { - if (sibling == mBuffer) + if (sibling == mState.source.get()) { - gl::Error error = copyToLocalRendertarget(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(copyToLocalRendertarget(context)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const +gl::Error EGLImageD3D::getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const { - if (mAttachmentBuffer) + if (mState.source.get()) { + ASSERT(!mRenderTarget); FramebufferAttachmentRenderTarget *rt = nullptr; - gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt); - if (error.isError()) - { - return error; - } - + ANGLE_TRY( + mState.source->getAttachmentRenderTarget(context, GL_NONE, mState.imageIndex, &rt)); *outRT = static_cast<RenderTargetD3D *>(rt); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } else { ASSERT(mRenderTarget); *outRT = mRenderTarget; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } -gl::Error EGLImageD3D::copyToLocalRendertarget() +gl::Error EGLImageD3D::copyToLocalRendertarget(const gl::Context *context) { - ASSERT(mBuffer != nullptr); - ASSERT(mAttachmentBuffer != nullptr); + ASSERT(mState.source.get() != nullptr); ASSERT(mRenderTarget == nullptr); RenderTargetD3D *curRenderTarget = nullptr; - gl::Error error = getRenderTarget(&curRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getRenderTarget(context, &curRenderTarget)); - // Clear the source image buffers - mBuffer = nullptr; - mAttachmentBuffer = nullptr; + // This only currently applies do D3D11, where it invalidates FBOs with this Image attached. + curRenderTarget->signalDirty(context); return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h index 6ec33e08f2..1ee7984426 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h @@ -9,9 +9,13 @@ #ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ #define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ -#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/renderer/ImageImpl.h" +namespace gl +{ +class Context; +} + namespace egl { class AttributeMap; @@ -19,6 +23,7 @@ class AttributeMap; namespace rx { +class FramebufferAttachmentObjectImpl; class TextureD3D; class RenderbufferD3D; class RendererD3D; @@ -27,30 +32,24 @@ class RenderTargetD3D; class EGLImageD3D final : public ImageImpl { public: - EGLImageD3D(RendererD3D *renderer, + EGLImageD3D(const egl::ImageState &state, EGLenum target, - egl::ImageSibling *buffer, - const egl::AttributeMap &attribs); + const egl::AttributeMap &attribs, + RendererD3D *renderer); ~EGLImageD3D() override; egl::Error initialize() override; - gl::Error orphan(egl::ImageSibling *sibling) override; + gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) override; - gl::Error getRenderTarget(RenderTargetD3D **outRT) const; + gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const; private: - gl::Error copyToLocalRendertarget(); + gl::Error copyToLocalRendertarget(const gl::Context *context); RendererD3D *mRenderer; - - egl::ImageSibling *mBuffer; - - gl::FramebufferAttachment::Target mAttachmentTarget; - FramebufferAttachmentObjectImpl *mAttachmentBuffer; - RenderTargetD3D *mRenderTarget; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp index 82967aced0..3d73b2c840 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -8,14 +8,16 @@ #include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "common/BitSetIterator.h" -#include "libANGLE/formatutils.h" +#include "common/bitset_utils.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Surface.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" -#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h" @@ -37,19 +39,19 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) { 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.colorF = state.getColorClearValue(); + clearParams.colorType = GL_FLOAT; + clearParams.colorMaskRed = blendState.colorMaskRed; + clearParams.colorMaskGreen = blendState.colorMaskGreen; + clearParams.colorMaskBlue = blendState.colorMaskBlue; + clearParams.colorMaskAlpha = blendState.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthValue = state.getDepthClearValue(); + clearParams.clearStencil = false; + clearParams.stencilValue = state.getStencilClearValue(); clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask; - clearParams.scissorEnabled = state.isScissorTestEnabled(); - clearParams.scissor = state.getScissor(); + clearParams.scissorEnabled = state.isScissorTestEnabled(); + clearParams.scissor = state.getScissor(); const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); if (mask & GL_COLOR_BUFFER_BIT) @@ -65,7 +67,8 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) if (mask & GL_DEPTH_BUFFER_BIT) { - if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL) + if (state.getDepthStencilState().depthMask && + framebufferObject->getDepthbuffer() != nullptr) { clearParams.clearDepth = true; } @@ -73,7 +76,7 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) if (mask & GL_STENCIL_BUFFER_BIT) { - if (framebufferObject->getStencilbuffer() != NULL && + if (framebufferObject->getStencilbuffer() != nullptr && framebufferObject->getStencilbuffer()->getStencilSize() > 0) { clearParams.clearStencil = true; @@ -82,10 +85,13 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) return clearParams; } - } -FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer) +ClearParameters::ClearParameters() = default; + +ClearParameters::ClearParameters(const ClearParameters &other) = default; + +FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer) : FramebufferImpl(data), mRenderer(renderer) { } @@ -94,20 +100,19 @@ FramebufferD3D::~FramebufferD3D() { } -gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) +gl::Error FramebufferD3D::clear(const gl::Context *context, GLbitfield mask) { - const gl::State &state = *data.state; - ClearParameters clearParams = GetClearParameters(state, mask); - return clear(data, clearParams); + ClearParameters clearParams = GetClearParameters(context->getGLState(), mask); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferfv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *values) { // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); if (buffer == GL_COLOR) { @@ -115,43 +120,43 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); } - clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; + clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_FLOAT; } if (buffer == GL_DEPTH) { clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; + clearParams.depthValue = values[0]; } - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferuiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLuint *values) { // glClearBufferuiv can only be called to clear a color buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + 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; + clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_UNSIGNED_INT; - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLint *values) { // glClearBufferiv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); if (buffer == GL_COLOR) { @@ -159,167 +164,154 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); } - clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; + clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_INT; } if (buffer == GL_STENCIL) { clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; + clearParams.stencilValue = values[0]; } - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferfi(const gl::Context *context, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + clearParams.clearDepth = true; + clearParams.depthValue = depth; + clearParams.clearStencil = true; + clearParams.stencilValue = stencil; - return clear(data, clearParams); + return clearImpl(context, clearParams); } -GLenum FramebufferD3D::getImplementationColorReadFormat() const +GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); if (readAttachment == nullptr) { return GL_NONE; } - RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + RenderTargetD3D *attachmentRenderTarget = nullptr; + gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget); if (error.isError()) { return GL_NONE; } GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); - const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + const gl::InternalFormat &implementationFormatInfo = + gl::GetSizedInternalFormatInfo(implementationFormat); - return implementationFormatInfo.format; + return implementationFormatInfo.getReadPixelsFormat(); } -GLenum FramebufferD3D::getImplementationColorReadType() const +GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); if (readAttachment == nullptr) { return GL_NONE; } - RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + RenderTargetD3D *attachmentRenderTarget = nullptr; + gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget); if (error.isError()) { return GL_NONE; } GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); - const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + const gl::InternalFormat &implementationFormatInfo = + gl::GetSizedInternalFormatInfo(implementationFormat); - return implementationFormatInfo.type; + return implementationFormatInfo.getReadPixelsType(context->getClientVersion()); } -gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +gl::Error FramebufferD3D::readPixels(const gl::Context *context, + const gl::Rectangle &origArea, + GLenum format, + GLenum type, + void *pixels) { - const gl::PixelPackState &packState = state.getPackState(); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); - const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = - sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength); - GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels( - outputPitch, 0, 0, packState.skipRows, packState.skipPixels); - - return readPixelsImpl(area, format, type, outputPitch, packState, - reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); -} - -gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, - GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) -{ - bool blitRenderTarget = false; - if ((mask & GL_COLOR_BUFFER_BIT) && - sourceFramebuffer->getReadColorbuffer() != nullptr && - mData.getFirstColorAttachment() != nullptr) + // Clip read area to framebuffer. + const gl::Extents fbSize = getState().getReadAttachment()->getSize(); + const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height); + gl::Rectangle area; + if (!ClipRectangle(origArea, fbRect, &area)) { - blitRenderTarget = true; + // nothing to read + return gl::NoError(); } - bool blitStencil = false; - if ((mask & GL_STENCIL_BUFFER_BIT) && - sourceFramebuffer->getStencilbuffer() != nullptr && - mData.getStencilAttachment() != nullptr) - { - blitStencil = true; - } + const gl::PixelPackState &packState = context->getGLState().getPackState(); - bool blitDepth = false; - if ((mask & GL_DEPTH_BUFFER_BIT) && - sourceFramebuffer->getDepthbuffer() != nullptr && - mData.getDepthAttachment() != nullptr) - { - blitDepth = true; - } + const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type); - if (blitRenderTarget || blitDepth || blitStencil) - { - const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL; - gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil, - filter, sourceFramebuffer); - if (error.isError()) - { - return error; - } - } + GLuint outputPitch = 0; + ANGLE_TRY_RESULT(sizedFormatInfo.computeRowPitch(type, origArea.width, packState.alignment, + packState.rowLength), + outputPitch); + GLuint outputSkipBytes = 0; + ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false), + outputSkipBytes); + outputSkipBytes += + (area.x - origArea.x) * sizedFormatInfo.pixelBytes + (area.y - origArea.y) * outputPitch; + + return readPixelsImpl(context, area, format, type, outputPitch, packState, + reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); +} - return gl::Error(GL_NO_ERROR); +gl::Error FramebufferD3D::blit(const gl::Context *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) +{ + const auto &glState = context->getGLState(); + const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer(); + const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr; + ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0, + (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0, + filter, sourceFramebuffer)); + + return gl::NoError(); } -bool FramebufferD3D::checkStatus() const +bool FramebufferD3D::checkStatus(const gl::Context *context) 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 (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr && - mData.getDepthStencilAttachment() == nullptr) + if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr && + mState.getDepthStencilAttachment() == nullptr) { return false; } - // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness - const auto &colorAttachments = mData.getColorAttachments(); - for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) + // D3D11 does not allow for overlapping RenderTargetViews. + // If WebGL compatibility is enabled, this has already been checked at a higher level. + ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages()); + if (!context->getExtensions().webglCompatibility) { - const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment]; - if (attachment.isAttached()) + if (!mState.colorAttachmentsAreUniqueImages()) { - for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++) - { - const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment]; - if (prevAttachment.isAttached() && - (attachment.id() == prevAttachment.id() && - attachment.type() == prevAttachment.type())) - { - return false; - } - } + return false; } } // D3D requires all render targets to have the same dimensions. - if (!mData.attachmentsHaveSameDimensions()) + if (!mState.attachmentsHaveSameDimensions()) { return false; } @@ -327,45 +319,52 @@ bool FramebufferD3D::checkStatus() const return true; } -void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) +void FramebufferD3D::syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) { - bool invalidateColorAttachmentCache = false; - if (!mColorAttachmentsForRender.valid()) { - invalidateColorAttachmentCache = true; + return; } - for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + for (auto dirtyBit : 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; + mColorAttachmentsForRender.reset(); } } +} - if (!invalidateColorAttachmentCache) +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context) +{ + gl::DrawBufferMask activeProgramOutputs = + context->getContextState().getState().getProgram()->getActiveOutputVariables(); + + if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs) { - return; + return mColorAttachmentsForRender.value(); } // Does not actually free memory gl::AttachmentList colorAttachmentsForRender; - const auto &colorAttachments = mData.getColorAttachments(); - const auto &drawBufferStates = mData.getDrawBufferStates(); + 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]; + GLenum drawBufferState = drawBufferStates[attachmentIndex]; const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex]; - if (colorAttachment.isAttached() && drawBufferState != GL_NONE) + if (colorAttachment.isAttached() && drawBufferState != GL_NONE && + activeProgramOutputs[attachmentIndex]) { - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + ASSERT(drawBufferState == GL_BACK || + drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); colorAttachmentsForRender.push_back(&colorAttachment); } else if (!workarounds.mrtPerfWorkaround) @@ -374,12 +373,32 @@ void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) } } + // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel + // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel + // shader. We add a dummy texture as render target in such case. + if (mRenderer->getWorkarounds().addDummyTextureNoRenderTarget && + colorAttachmentsForRender.empty()) + { + static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32, + "Size of active program outputs should less or equal than 32."); + GLenum i = static_cast<GLenum>( + gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits()))); + + gl::Texture *dummyTex = nullptr; + // TODO(Jamie): Handle error if dummy texture can't be created. + ANGLE_SWALLOW_ERR(mRenderer->getIncompleteTexture(context, GL_TEXTURE_2D, &dummyTex)); + if (dummyTex) + { + gl::ImageIndex index = gl::ImageIndex::Make2D(0); + gl::FramebufferAttachment *dummyAttach = new gl::FramebufferAttachment( + context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + i, index, dummyTex); + colorAttachmentsForRender.push_back(dummyAttach); + } + } + mColorAttachmentsForRender = std::move(colorAttachmentsForRender); -} + mCurrentActiveProgramOutputs = activeProgramOutputs; -const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const -{ - ASSERT(mColorAttachmentsForRender.valid()); return mColorAttachmentsForRender.value(); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h index eb839c4364..a7312fdef4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -9,9 +9,10 @@ #ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ #define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ -#include <vector> #include <cstdint> +#include <vector> +#include "common/Color.h" #include "common/Optional.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/FramebufferImpl.h" @@ -22,32 +23,33 @@ class FramebufferAttachment; struct PixelPackState; typedef std::vector<const FramebufferAttachment *> AttachmentList; - } namespace rx { class RendererD3D; class RenderTargetD3D; -struct WorkaroundsD3D; struct ClearParameters { + ClearParameters(); + ClearParameters(const ClearParameters &other); + bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - gl::ColorF colorFClearValue; - gl::ColorI colorIClearValue; - gl::ColorUI colorUIClearValue; - GLenum colorClearType; + gl::ColorF colorF; + gl::ColorI colorI; + gl::ColorUI colorUI; + GLenum colorType; bool colorMaskRed; bool colorMaskGreen; bool colorMaskBlue; bool colorMaskAlpha; bool clearDepth; - float depthClearValue; + float depthValue; bool clearStencil; - GLint stencilClearValue; + GLint stencilValue; GLuint stencilWriteMask; bool scissorEnabled; @@ -57,61 +59,76 @@ struct ClearParameters class FramebufferD3D : public FramebufferImpl { public: - FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer); - virtual ~FramebufferD3D(); + FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer); + ~FramebufferD3D() override; - gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::Data &data, + gl::Error clear(const gl::Context *context, GLbitfield mask) override; + gl::Error clearBufferfv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::Data &data, + gl::Error clearBufferuiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::Data &data, + gl::Error clearBufferiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::Data &data, + gl::Error clearBufferfi(const gl::Context *context, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; - GLenum getImplementationColorReadFormat() const override; - GLenum getImplementationColorReadType() const override; - gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override; + GLenum getImplementationColorReadFormat(const gl::Context *context) const override; + GLenum getImplementationColorReadType(const gl::Context *context) const override; + gl::Error readPixels(const gl::Context *context, + const gl::Rectangle &area, + GLenum format, + GLenum type, + void *pixels) override; - gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, - GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; + gl::Error blit(const gl::Context *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) override; - bool checkStatus() const override; + bool checkStatus(const gl::Context *context) const override; - void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; + void syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) override; - const gl::AttachmentList &getColorAttachmentsForRender() const; + const gl::AttachmentList &getColorAttachmentsForRender(const gl::Context *context); private: - virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0; + virtual gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) = 0; - virtual gl::Error readPixelsImpl(const gl::Rectangle &area, + virtual gl::Error readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const = 0; - - virtual gl::Error blit(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; + uint8_t *pixels) = 0; + + virtual gl::Error blitImpl(const gl::Context *context, + 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; + gl::DrawBufferMask mCurrentActiveProgramOutputs; }; - } -#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index df0257e370..5d47308d67 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -6,6 +6,8 @@ #include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include <sstream> + #include "common/utilities.h" #include "libANGLE/Program.h" #include "libANGLE/features.h" @@ -25,15 +27,6 @@ namespace #define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } -#if defined(ANGLE_MINGW32_COMPAT) -#ifndef D3DCOMPILE_RESERVED16 -#define D3DCOMPILE_RESERVED16 0x10000 -#endif -#ifndef D3DCOMPILE_RESERVED17 -#define D3DCOMPILE_RESERVED17 0x20000 -#endif -#endif - struct CompilerFlagInfo { UINT mFlag; @@ -119,11 +112,11 @@ HLSLCompiler::~HLSLCompiler() release(); } -gl::Error HLSLCompiler::initialize() +gl::Error HLSLCompiler::ensureInitialized() { if (mInitialized) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize"); @@ -162,7 +155,6 @@ gl::Error HLSLCompiler::initialize() break; } - if (!mD3DCompilerModule) { // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. @@ -171,7 +163,8 @@ gl::Error HLSLCompiler::initialize() if (!mD3DCompilerModule) { - return gl::Error(GL_INVALID_OPERATION, "No D3D compiler module found - aborting!\n"); + ERR() << "D3D compiler module not found."; + return gl::OutOfMemory() << "D3D compiler module not found."; } mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile")); @@ -190,11 +183,11 @@ gl::Error HLSLCompiler::initialize() if (mD3DCompileFunc == nullptr) { - return gl::Error(GL_INVALID_OPERATION, "Error finding D3DCompile entry point"); + return gl::OutOfMemory() << "Error finding D3DCompile entry point."; } mInitialized = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void HLSLCompiler::release() @@ -213,11 +206,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros, ID3DBlob **outCompiledBlob, std::string *outDebugInfo) { - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } + ASSERT(mInitialized); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) ASSERT(mD3DCompilerModule); @@ -228,7 +217,9 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string if (gl::DebugAnnotationsActive()) { std::string sourcePath = getTempPath(); - std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); + std::ostringstream stream; + stream << "#line 2 \"" << sourcePath << "\"\n\n" << hlsl; + std::string sourceText = stream.str(); writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); } #endif @@ -255,8 +246,11 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string SafeRelease(errorMessage); infoLog.appendSanitized(message.c_str()); - TRACE("\n%s", hlsl.c_str()); - TRACE("\n%s", message.c_str()); + + // This produces unbelievable amounts of spam in about:gpu. + // WARN() << std::endl << hlsl; + + WARN() << std::endl << message; 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", @@ -304,20 +298,17 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string } std::string disassembly; - error = disassembleBinary(binary, &disassembly); - if (error.isError()) - { - return error; - } + ANGLE_TRY(disassembleBinary(binary, &disassembly)); (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n"; #endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } if (result == E_OUTOFMEMORY) { *outCompiledBlob = nullptr; - return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); + return gl::OutOfMemory() + << "HLSL compiler had an unexpected failure, " << gl::FmtHR(result); } infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. (" @@ -331,16 +322,12 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string // None of the configurations succeeded in compiling this shader but the compiler is still intact *outCompiledBlob = nullptr; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut) { - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureInitialized()); // Retrieve disassembly UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; @@ -361,7 +348,7 @@ gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *d SafeRelease(disassembly); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h index 3c0d2adcac..c8f9eac290 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h @@ -1,3 +1,11 @@ +// +// 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. +// +// HLSLCompiler: Wrapper for the D3DCompiler DLL. +// + #ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ #define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ @@ -41,9 +49,9 @@ class HLSLCompiler : angle::NonCopyable ID3DBlob **outCompiledBlob, std::string *outDebugInfo); gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut); + gl::Error ensureInitialized(); private: - gl::Error initialize(); bool mInitialized; HMODULE mD3DCompilerModule; @@ -53,4 +61,4 @@ class HLSLCompiler : angle::NonCopyable } -#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ +#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp index ead5db6453..dbbcbbed2a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp @@ -29,4 +29,34 @@ ImageD3D::ImageD3D() { } +gl::Error ImageD3D::setManagedSurface2D(const gl::Context *context, + TextureStorage *storage, + int level) +{ + return gl::NoError(); +} + +gl::Error ImageD3D::setManagedSurfaceCube(const gl::Context *context, + TextureStorage *storage, + int face, + int level) +{ + return gl::NoError(); +} + +gl::Error ImageD3D::setManagedSurface3D(const gl::Context *context, + TextureStorage *storage, + int level) +{ + return gl::NoError(); +} + +gl::Error ImageD3D::setManagedSurface2DArray(const gl::Context *context, + TextureStorage *storage, + int layer, + int level) +{ + return gl::NoError(); +} + } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h index 2afe1cfabf..1b7235fbaa 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h @@ -17,6 +17,7 @@ namespace gl { +class Context; class Framebuffer; struct ImageIndex; struct Box; @@ -51,18 +52,40 @@ class ImageD3D : angle::NonCopyable virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; - virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 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, + virtual gl::Error loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) = 0; + virtual gl::Error loadCompressedData(const gl::Context *context, + const gl::Box &area, + const void *input) = 0; + + virtual gl::Error setManagedSurface2D(const gl::Context *context, + TextureStorage *storage, + int level); + virtual gl::Error setManagedSurfaceCube(const gl::Context *context, + TextureStorage *storage, + int face, + int level); + virtual gl::Error setManagedSurface3D(const gl::Context *context, + TextureStorage *storage, + int level); + virtual gl::Error setManagedSurface2DArray(const gl::Context *context, + TextureStorage *storage, + int layer, + int level); + virtual gl::Error copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) = 0; + + virtual gl::Error copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, TextureStorage *source) = 0; - virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + virtual gl::Error copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) = 0; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp index 677b8bb240..937512a96a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp @@ -71,7 +71,8 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem // 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."); + return gl::OutOfMemory() + << "Mapping of internal index buffer would cause an integer overflow."; } gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory); @@ -79,7 +80,7 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem { if (outMappedMemory) { - *outMappedMemory = NULL; + *outMappedMemory = nullptr; } return error; } @@ -90,7 +91,7 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem } mWritePosition += size; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBufferInterface::unmapBuffer() @@ -145,24 +146,16 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G unsigned int writePos = getWritePosition(); if (size > curBufferSize) { - gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setBufferSize(std::max(size, 2 * curBufferSize), indexType)); setWritePosition(0); } else if (writePos + size > curBufferSize || writePos + size < writePos) { - gl::Error error = discard(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(discard()); setWritePosition(0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } @@ -184,13 +177,13 @@ gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLen } else if (curSize >= size && indexType == getIndexType()) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } else { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); + return gl::InternalError() << "Internal static index buffers can't be resized"; } } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h index 0b7b28ddf0..969cf6ae63 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h @@ -81,7 +81,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface { public: explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory); - ~StreamingIndexBufferInterface(); + ~StreamingIndexBufferInterface() override; gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; }; @@ -90,7 +90,7 @@ class StaticIndexBufferInterface : public IndexBufferInterface { public: explicit StaticIndexBufferInterface(BufferFactoryD3D *factory); - ~StaticIndexBufferInterface(); + ~StaticIndexBufferInterface() override; gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp index f1ba3d3db0..e974097b45 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -10,10 +10,12 @@ #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/Context.h" +#include "libANGLE/VertexArray.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" namespace rx { @@ -76,11 +78,12 @@ void ConvertIndices(GLenum sourceType, ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count, usePrimitiveRestartFixedIndex); } - else UNREACHABLE(); + else + UNREACHABLE(); } gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, - const GLvoid *data, + const void *data, unsigned int count, GLenum srcType, GLenum dstType, @@ -91,50 +94,59 @@ gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, 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); + return gl::OutOfMemory() << "Reserving " << count << " indices of " << dstTypeInfo.bytes + << " bytes each exceeds the maximum buffer size."; } unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift; - gl::Error error = buffer->reserveBufferSpace(bufferSizeRequired, dstType); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->reserveBufferSpace(bufferSizeRequired, dstType)); void *output = nullptr; - error = buffer->mapBuffer(bufferSizeRequired, &output, offset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->mapBuffer(bufferSizeRequired, &output, offset)); ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex); - error = buffer->unmapBuffer(); - if (error.isError()) + ANGLE_TRY(buffer->unmapBuffer()); + return gl::NoError(); +} + +unsigned int ElementTypeSize(GLenum elementType) +{ + switch (elementType) { - return error; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + default: + UNREACHABLE(); + return 0; } - - return gl::Error(GL_NO_ERROR); } } // anonymous namespace -IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) - : mFactory(factory), - mRendererClass(rendererClass), - mStreamingBufferShort(nullptr), - mStreamingBufferInt(nullptr) +bool IsOffsetAligned(GLenum elementType, unsigned int offset) +{ + return (offset % ElementTypeSize(elementType) == 0); +} + +// IndexDataManager implementation. +IndexDataManager::IndexDataManager(BufferFactoryD3D *factory) + : mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt() { } IndexDataManager::~IndexDataManager() { - SafeDelete(mStreamingBufferShort); - SafeDelete(mStreamingBufferInt); +} + +void IndexDataManager::deinitialize() +{ + mStreamingBufferShort.reset(); + mStreamingBufferInt.reset(); } // This function translates a GL-style indices into DX-style indices, with their description @@ -143,43 +155,31 @@ IndexDataManager::~IndexDataManager() // 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, +// 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(const gl::Context *context, + GLenum srcType, + GLenum dstType, GLsizei count, gl::Buffer *glBuffer, - const GLvoid *indices, - TranslatedIndexData *translated, - bool primitiveRestartFixedIndexEnabled) + const void *indices, + TranslatedIndexData *translated) { - // 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->indexType = dstType; translated->srcIndexData.srcBuffer = buffer; translated->srcIndexData.srcIndices = indices; translated->srcIndexData.srcIndexType = srcType; translated->srcIndexData.srcCount = count; + // Context can be nullptr in perf tests. + bool primitiveRestartFixedIndexEnabled = + context ? context->getGLState().isPrimitiveRestartEnabled() : false; + // Case 1: the indices are passed by pointer, which forces the streaming of index data if (glBuffer == nullptr) { @@ -192,95 +192,69 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, 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; - } + bool offsetAligned = IsOffsetAligned(srcType, offset); // Case 2a: the buffer can be used directly - if (offsetAligned && buffer->supportsDirectBinding() && - dstType == srcType && !primitiveRestartWorkaround) + if (offsetAligned && buffer->supportsDirectBinding() && dstType == srcType) { - translated->storage = buffer; + translated->storage = buffer; translated->indexBuffer = nullptr; - translated->serial = buffer->getSerial(); - translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->serial = buffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); translated->startOffset = offset; - buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift); - return gl::Error(GL_NO_ERROR); - } - else - { - translated->storage = nullptr; + return gl::NoError(); } + 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; + bool staticBufferUsable = + staticBuffer && offsetAligned && staticBuffer->getIndexType() == dstType; if (staticBufferInitialized && !staticBufferUsable) { - buffer->invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + buffer->invalidateStaticData(context); staticBuffer = nullptr; } if (staticBuffer == nullptr || !offsetAligned) { const uint8_t *bufferData = nullptr; - gl::Error error = buffer->getData(&bufferData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->getData(context, &bufferData)); ASSERT(bufferData != nullptr); - error = streamIndexData(bufferData + offset, count, srcType, dstType, - primitiveRestartFixedIndexEnabled, translated); - if (error.isError()) - { - return error; - } + ANGLE_TRY(streamIndexData(bufferData + offset, count, srcType, dstType, + primitiveRestartFixedIndexEnabled, translated)); + buffer->promoteStaticUsage(context, count << srcTypeInfo.bytesShift); } else { if (!staticBufferInitialized) { const uint8_t *bufferData = nullptr; - gl::Error error = buffer->getData(&bufferData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->getData(context, &bufferData)); 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; - } + ANGLE_TRY(StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType, + primitiveRestartFixedIndexEnabled, nullptr)); } ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType); translated->indexBuffer = staticBuffer->getIndexBuffer(); - translated->serial = staticBuffer->getSerial(); - translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->serial = staticBuffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error IndexDataManager::streamIndexData(const GLvoid *data, +gl::Error IndexDataManager::streamIndexData(const void *data, unsigned int count, GLenum srcType, GLenum dstType, @@ -290,65 +264,57 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data, const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); IndexBufferInterface *indexBuffer = nullptr; - gl::Error error = getStreamingIndexBuffer(dstType, &indexBuffer); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getStreamingIndexBuffer(dstType, &indexBuffer)); ASSERT(indexBuffer != nullptr); unsigned int offset; - StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex, - &offset); + ANGLE_TRY(StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, + usePrimitiveRestartFixedIndex, &offset)); translated->indexBuffer = indexBuffer->getIndexBuffer(); - translated->serial = indexBuffer->getSerial(); - translated->startIndex = (offset >> dstTypeInfo.bytesShift); + translated->serial = indexBuffer->getSerial(); + translated->startIndex = (offset >> dstTypeInfo.bytesShift); translated->startOffset = offset; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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; - } - } + ASSERT(destinationIndexType == GL_UNSIGNED_SHORT || destinationIndexType == GL_UNSIGNED_INT); - *outBuffer = mStreamingBufferInt; - return gl::Error(GL_NO_ERROR); - } - else + auto &streamingBuffer = + (destinationIndexType == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + if (!streamingBuffer) { - ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); + StreamingBuffer newBuffer(new StreamingIndexBufferInterface(mFactory)); + ANGLE_TRY(newBuffer->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, destinationIndexType)); + streamingBuffer = std::move(newBuffer); + } - if (!mStreamingBufferShort) + *outBuffer = streamingBuffer.get(); + return gl::NoError(); +} + +GLenum GetIndexTranslationDestType(GLenum srcType, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround) +{ + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + if (usePrimitiveRestartWorkaround) + { + const gl::IndexRange &indexRange = lazyIndexRange.getIndexRange().value(); + if (indexRange.end == gl::GetPrimitiveRestartIndex(srcType)) { - mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory); - gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, - GL_UNSIGNED_SHORT); - if (error.isError()) - { - SafeDelete(mStreamingBufferShort); - return error; - } + return GL_UNSIGNED_INT; } - - *outBuffer = mStreamingBufferShort; - return gl::Error(GL_NO_ERROR); } -} + return (srcType == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h index 44eb68c071..77f05df92d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -19,7 +19,10 @@ namespace { - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +enum +{ + INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) +}; } namespace gl @@ -39,7 +42,7 @@ class RendererD3D; struct SourceIndexData { BufferD3D *srcBuffer; - const GLvoid *srcIndices; + const void *srcIndices; unsigned int srcCount; GLenum srcIndexType; bool srcIndicesChanged; @@ -47,9 +50,8 @@ struct SourceIndexData struct TranslatedIndexData { - gl::IndexRange indexRange; unsigned int startIndex; - unsigned int startOffset; // In bytes + unsigned int startOffset; // In bytes IndexBuffer *indexBuffer; BufferD3D *storage; @@ -62,18 +64,21 @@ struct TranslatedIndexData class IndexDataManager : angle::NonCopyable { public: - explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); + explicit IndexDataManager(BufferFactoryD3D *factory); virtual ~IndexDataManager(); - gl::Error prepareIndexData(GLenum srcType, + void deinitialize(); + + gl::Error prepareIndexData(const gl::Context *context, + GLenum srcType, + GLenum dstType, GLsizei count, gl::Buffer *glBuffer, - const GLvoid *indices, - TranslatedIndexData *translated, - bool primitiveRestartFixedIndexEnabled); + const void *indices, + TranslatedIndexData *translated); private: - gl::Error streamIndexData(const GLvoid *data, + gl::Error streamIndexData(const void *data, unsigned int count, GLenum srcType, GLenum dstType, @@ -82,12 +87,19 @@ class IndexDataManager : angle::NonCopyable gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); + using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>; + BufferFactoryD3D *const mFactory; - RendererClass mRendererClass; - StreamingIndexBufferInterface *mStreamingBufferShort; - StreamingIndexBufferInterface *mStreamingBufferInt; + std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort; + std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt; }; -} +GLenum GetIndexTranslationDestType(GLenum srcType, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround); + +bool IsOffsetAligned(GLenum elementType, unsigned int offset); + +} // namespace rx -#endif // LIBANGLE_INDEXDATAMANAGER_H_ +#endif // LIBANGLE_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp new file mode 100644 index 0000000000..113bad647c --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h new file mode 100644 index 0000000000..365448488d --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp index 72c6f1a1a9..afc318d9fa 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -8,31 +8,41 @@ #include "libANGLE/renderer/d3d/ProgramD3D.h" -#include "common/BitSetIterator.h" +#include "common/bitset_utils.h" +#include "common/string_utils.h" #include "common/utilities.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Program.h" +#include "libANGLE/ProgramLinkedResources.h" +#include "libANGLE/Uniform.h" #include "libANGLE/VertexArray.h" #include "libANGLE/features.h" +#include "libANGLE/queryconversions.h" +#include "libANGLE/renderer/ContextImpl.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" +using namespace angle; + namespace rx { namespace { -gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) +void GetDefaultInputLayoutFromShader(const gl::Context *context, + gl::Shader *vertexShader, + gl::InputLayout *inputLayoutOut) { - gl::InputLayout defaultLayout; - for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes()) + inputLayoutOut->clear(); + + for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes(context)) { if (shaderAttr.type != GL_NONE) { @@ -47,301 +57,256 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) gl::VertexFormatType defaultType = gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt); - defaultLayout.push_back(defaultType); + inputLayoutOut->push_back(defaultType); } } } - - return defaultLayout; } -std::vector<GLenum> GetDefaultOutputLayoutFromShader( - const std::vector<PixelShaderOutputVariable> &shaderOutputVars) +void GetDefaultOutputLayoutFromShader( + const std::vector<PixelShaderOutputVariable> &shaderOutputVars, + std::vector<GLenum> *outputLayoutOut) { - std::vector<GLenum> defaultPixelOutput; + outputLayoutOut->clear(); if (!shaderOutputVars.empty()) { - defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + - static_cast<unsigned int>(shaderOutputVars[0].outputIndex)); + outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 + + static_cast<unsigned int>(shaderOutputVars[0].outputIndex)); } - - return defaultPixelOutput; } -bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +template <typename T, int cols, int rows> +bool TransposeExpandMatrix(T *target, const GLfloat *value) { - return var.isRowMajorLayout; -} + constexpr int targetWidth = 4; + constexpr int targetHeight = rows; + constexpr int srcWidth = rows; + constexpr int srcHeight = cols; -bool IsRowMajorLayout(const sh::ShaderVariable &var) -{ - return false; -} + constexpr int copyWidth = std::min(targetHeight, srcWidth); + constexpr int copyHeight = std::min(targetWidth, srcHeight); -struct AttributeSorter -{ - AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices) - : originalIndices(&semanticIndices) + T staging[targetWidth * targetHeight] = {0}; + + for (int x = 0; x < copyWidth; x++) { + for (int y = 0; y < copyHeight; y++) + { + staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]); + } } - bool operator()(int a, int b) + if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0) { - int indexA = (*originalIndices)[a]; - int indexB = (*originalIndices)[b]; - - if (indexA == -1) - return false; - if (indexB == -1) - return true; - return (indexA < indexB); + return false; } - const ProgramD3D::SemanticIndexArray *originalIndices; -}; - -// 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); + memcpy(target, staging, targetWidth * targetHeight * sizeof(T)); + return true; } -std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, - const gl::Shader &fragmentShader, - const std::vector<std::string> &tfVaryings) +template <typename T, int cols, int rows> +bool ExpandMatrix(T *target, const GLfloat *value) { - std::vector<PackedVarying> packedVaryings; + constexpr int targetWidth = 4; + constexpr int targetHeight = rows; + constexpr int srcWidth = cols; + constexpr int srcHeight = rows; - for (const sh::Varying &output : vertexShader.getVaryings()) - { - bool packed = false; + constexpr int copyWidth = std::min(targetWidth, srcWidth); + constexpr int copyHeight = std::min(targetHeight, srcHeight); - // 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; - } - } + T staging[targetWidth * targetHeight] = {0}; - // Keep Transform FB varyings in the merged list always. - if (!packed) + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) { - 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; - } - } + staging[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]); } } - std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying); + if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0) + { + return false; + } - return packedVaryings; + memcpy(target, staging, targetWidth * targetHeight * sizeof(T)); + return true; } -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) +gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode) { - for (const VarT &field : fields) + switch (drawMode) { - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); + // Uses the point sprite geometry shader. + case GL_POINTS: + return gl::PRIMITIVE_POINTS; - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + // All line drawing uses the same geometry shader. + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + return gl::PRIMITIVE_LINES; - for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); + // The triangle fan primitive is emulated with strips in D3D11. + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + return gl::PRIMITIVE_TRIANGLES; - const std::string uniformElementName = - fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout, - blockInfoOut); + // Special case for triangle strips. + case GL_TRIANGLE_STRIP: + return gl::PRIMITIVE_TRIANGLE_STRIP; - encoder->exitAggregateType(); - } - } - else - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - (*blockInfoOut)[fieldName] = - encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); - } + default: + UNREACHABLE(); + return gl::PRIMITIVE_TYPE_MAX; } } -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 FindFlatInterpolationVarying(const std::vector<sh::Varying> &varyings) { - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) + // Note: this assumes nested structs can only be packed with one interpolation. + for (const auto &varying : varyings) { - 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++) + if (varying.interpolation == sh::INTERPOLATION_FLAT) { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + return true; } } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) + + return false; +} + +// Helper method to de-tranpose a matrix uniform for an API query. +void GetMatrixUniform(GLint columns, GLint rows, GLfloat *dataOut, const GLfloat *source) +{ + for (GLint col = 0; col < columns; ++col) { - for (int x = 0; x < targetWidth; x++) + for (GLint row = 0; row < rows; ++row) { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + GLfloat *outptr = dataOut + ((col * rows) + row); + const GLfloat *inptr = source + ((row * 4) + col); + *outptr = *inptr; } } +} - return dirty; +template <typename NonFloatT> +void GetMatrixUniform(GLint columns, GLint rows, NonFloatT *dataOut, const NonFloatT *source) +{ + UNREACHABLE(); } -template <typename T> -bool ExpandMatrix(T *target, - const GLfloat *value, - int targetWidth, - int targetHeight, - int srcWidth, - int srcHeight) +class UniformBlockInfo final : angle::NonCopyable { - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); + public: + UniformBlockInfo() {} - for (int y = 0; y < copyHeight; y++) + void getShaderBlockInfo(const gl::Context *context, gl::Shader *shader); + + bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut); + bool getBlockMemberInfo(const std::string &name, + const std::string &mappedName, + sh::BlockMemberInfo *infoOut); + + private: + size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock); + + std::map<std::string, size_t> mBlockSizes; + sh::BlockLayoutMap mBlockLayout; +}; + +void UniformBlockInfo::getShaderBlockInfo(const gl::Context *context, gl::Shader *shader) +{ + for (const sh::InterfaceBlock &interfaceBlock : shader->getUniformBlocks(context)) { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), - &dirty); - } + if (!interfaceBlock.staticUse && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (mBlockSizes.count(interfaceBlock.name) > 0) + continue; + + size_t dataSize = getBlockInfo(interfaceBlock); + mBlockSizes[interfaceBlock.name] = dataSize; } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) +} + +size_t UniformBlockInfo::getBlockInfo(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, false); + sh::BlockLayoutEncoder *encoder = nullptr; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140) { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } + encoder = &std140Encoder; } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) + else { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } + encoder = &hlslEncoder; } - return dirty; + sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, + interfaceBlock.isRowMajorLayout, &mBlockLayout); + + return encoder->getBlockSize(); } -gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode) +bool UniformBlockInfo::getBlockSize(const std::string &name, + const std::string &mappedName, + size_t *sizeOut) { - switch (drawMode) + size_t nameLengthWithoutArrayIndex; + gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex); + std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex); + auto sizeIter = mBlockSizes.find(baseName); + if (sizeIter == mBlockSizes.end()) { - // 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; + *sizeOut = 0; + return false; + } - // Special case for triangle strips. - case GL_TRIANGLE_STRIP: - return gl::PRIMITIVE_TRIANGLE_STRIP; + *sizeOut = sizeIter->second; + return true; +}; - default: - UNREACHABLE(); - return gl::PRIMITIVE_TYPE_MAX; +bool UniformBlockInfo::getBlockMemberInfo(const std::string &name, + const std::string &mappedName, + sh::BlockMemberInfo *infoOut) +{ + auto infoIter = mBlockLayout.find(name); + if (infoIter == mBlockLayout.end()) + { + *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; } -} + + *infoOut = infoIter->second; + return true; +}; } // anonymous namespace // D3DUniform Implementation -D3DUniform::D3DUniform(GLenum typeIn, +D3DUniform::D3DUniform(GLenum type, const std::string &nameIn, - unsigned int arraySizeIn, + const std::vector<unsigned int> &arraySizesIn, bool defaultBlock) - : type(typeIn), + : typeInfo(gl::GetUniformTypeInfo(type)), name(nameIn), - arraySize(arraySizeIn), - data(nullptr), - dirty(true), + arraySizes(arraySizesIn), + vsData(nullptr), + psData(nullptr), + csData(nullptr), vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX), + csRegisterIndex(GL_INVALID_INDEX), registerCount(0), registerElement(0) { @@ -350,23 +315,36 @@ D3DUniform::D3DUniform(GLenum typeIn, // 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(); + // Use the row count as register count, will work for non-square matrices. + registerCount = typeInfo.rowCount * getArraySizeProduct(); } } D3DUniform::~D3DUniform() { - SafeDeleteArray(data); +} + +unsigned int D3DUniform::getArraySizeProduct() const +{ + return gl::ArraySizeProduct(arraySizes); +} + +const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const +{ + ASSERT((!isArray() && elementIndex == 0) || + (isArray() && elementIndex < getArraySizeProduct())); + + if (isSampler()) + { + return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]); + } + + return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u); } bool D3DUniform::isSampler() const { - return gl::IsSamplerType(type); + return typeInfo.isSampler; } bool D3DUniform::isReferencedByVertexShader() const @@ -379,6 +357,23 @@ bool D3DUniform::isReferencedByFragmentShader() const return psRegisterIndex != GL_INVALID_INDEX; } +bool D3DUniform::isReferencedByComputeShader() const +{ + return csRegisterIndex != GL_INVALID_INDEX; +} + +const uint8_t *D3DUniform::firstNonNullData() const +{ + ASSERT(vsData || psData || csData || !mSamplerData.empty()); + + if (!mSamplerData.empty()) + { + return reinterpret_cast<const uint8_t *>(mSamplerData.data()); + } + + return vsData ? vsData : (psData ? psData : csData); +} + // D3DVarying Implementation D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) @@ -398,16 +393,17 @@ D3DVarying::D3DVarying(const std::string &semanticNameIn, // ProgramD3DMetadata Implementation -ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel, - const std::string &shaderModelSuffix, - bool usesInstancedPointSpriteEmulation, - bool usesViewScale, +ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer, const ShaderD3D *vertexShader, const ShaderD3D *fragmentShader) - : mRendererMajorShaderModel(rendererMajorShaderModel), - mShaderModelSuffix(shaderModelSuffix), - mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation), - mUsesViewScale(usesViewScale), + : mRendererMajorShaderModel(renderer->getMajorShaderModel()), + mShaderModelSuffix(renderer->getShaderModelSuffix()), + mUsesInstancedPointSpriteEmulation( + renderer->getWorkarounds().useInstancedPointSpriteEmulation), + mUsesViewScale(renderer->presentPathFastEnabled()), + mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()), + mUsesViewID(fragmentShader->usesViewID()), + mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()), mVertexShader(vertexShader), mFragmentShader(fragmentShader) { @@ -418,12 +414,13 @@ int ProgramD3DMetadata::getRendererMajorShaderModel() const return mRendererMajorShaderModel; } -bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const +bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const { - return (mFragmentShader->usesFragColor() && data.clientVersion < 3); + return (mFragmentShader->usesFragColor() && mFragmentShader->usesMultipleRenderTargets() && + data.getClientMajorVersion() < 3); } -bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const +bool ProgramD3DMetadata::usesFragDepth() const { return mFragmentShader->usesFragDepth(); } @@ -445,7 +442,8 @@ bool ProgramD3DMetadata::usesPointSize() const bool ProgramD3DMetadata::usesInsertedPointCoordValue() const { - return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4; + return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() && + mRendererMajorShaderModel >= 4; } bool ProgramD3DMetadata::usesViewScale() const @@ -453,15 +451,29 @@ bool ProgramD3DMetadata::usesViewScale() const return mUsesViewScale; } +bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const +{ + return mHasANGLEMultiviewEnabled; +} + +bool ProgramD3DMetadata::usesViewID() const +{ + return mUsesViewID; +} + +bool ProgramD3DMetadata::canSelectViewInVertexShader() const +{ + return mCanSelectViewInVertexShader; +} + bool ProgramD3DMetadata::addsPointCoordToVertexShader() const { - // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader + // 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. - // GeometryShader PointSprite emulation does not require this additional entry because the - // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the - // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs - // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need - // gl_PointSize in VS_OUTPUT. + // 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(); } @@ -509,24 +521,44 @@ ProgramD3D::VertexExecutable::~VertexExecutable() } // 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->resize(inputLayout.size()); + signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT); for (size_t index = 0; index < inputLayout.size(); ++index) { gl::VertexFormatType vertexFormatType = inputLayout[index]; - bool converted = false; - if (vertexFormatType != gl::VERTEX_FORMAT_INVALID) - { - VertexConversionType conversionType = - renderer->getVertexConversionType(vertexFormatType); - converted = ((conversionType & VERTEX_CONVERT_GPU) != 0); - } + if (vertexFormatType == gl::VERTEX_FORMAT_INVALID) + continue; + + VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType); + if ((conversionType & VERTEX_CONVERT_GPU) == 0) + continue; - (*signatureOut)[index] = converted; + GLenum componentType = renderer->getVertexComponentType(vertexFormatType); + (*signatureOut)[index] = GetAttribType(componentType); } } @@ -535,9 +567,9 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) size_t limit = std::max(mSignature.size(), signature.size()); for (size_t index = 0; index < limit; ++index) { - // treat undefined indexes as 'not converted' - bool a = index < signature.size() ? signature[index] : false; - bool b = index < mSignature.size() ? mSignature[index] : false; + // 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; } @@ -562,19 +594,25 @@ ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureTy unsigned int ProgramD3D::mCurrentSerial = 1; -ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer) - : ProgramImpl(data), +ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer) + : ProgramImpl(state), mRenderer(renderer), - mDynamicHLSL(NULL), - mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr), + mDynamicHLSL(nullptr), + mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX), + mComputeExecutable(nullptr), mUsesPointSize(false), mUsesFlatInterpolation(false), - mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL), + mVertexUniformStorage(nullptr), + mFragmentUniformStorage(nullptr), + mComputeUniformStorage(nullptr), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), + mUsedComputeSamplerRange(0), mDirtySamplerMapping(true), - mSerial(issueSerial()) + mSerial(issueSerial()), + mVertexUniformsDirty(true), + mFragmentUniformsDirty(true), + mComputeUniformsDirty(true) { mDynamicHLSL = new DynamicHLSL(renderer); } @@ -590,14 +628,22 @@ bool ProgramD3D::usesPointSpriteEmulation() const return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; } +bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const +{ + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); +} + bool ProgramD3D::usesGeometryShader(GLenum drawMode) const { + if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader()) + { + return true; + } if (drawMode != GL_POINTS) { return mUsesFlatInterpolation; } - - return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); + return usesGeometryShaderForPointSpriteEmulation(); } bool ProgramD3D::usesInstancedPointSpriteEmulation() const @@ -627,6 +673,13 @@ GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; } break; + case gl::SAMPLER_COMPUTE: + ASSERT(samplerIndex < caps.maxComputeTextureImageUnits); + if (samplerIndex < mSamplersCS.size() && mSamplersCS[samplerIndex].active) + { + logicalTextureUnit = mSamplersCS[samplerIndex].logicalTextureUnit; + } + break; default: UNREACHABLE(); } @@ -654,6 +707,10 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp ASSERT(samplerIndex < mSamplersVS.size()); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; + case gl::SAMPLER_COMPUTE: + ASSERT(samplerIndex < mSamplersCS.size()); + ASSERT(mSamplersCS[samplerIndex].active); + return mSamplersCS[samplerIndex].textureType; default: UNREACHABLE(); } @@ -661,7 +718,7 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp return GL_TEXTURE_2D; } -GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const +GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const { switch (type) { @@ -669,17 +726,19 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const return mUsedPixelSamplerRange; case gl::SAMPLER_VERTEX: return mUsedVertexSamplerRange; + case gl::SAMPLER_COMPUTE: + return mUsedComputeSamplerRange; default: UNREACHABLE(); - return 0; + return 0u; } } -void ProgramD3D::updateSamplerMapping() +ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping() { if (!mDirtySamplerMapping) { - return; + return SamplerMapping::WasClean; } mDirtySamplerMapping = false; @@ -687,14 +746,10 @@ void ProgramD3D::updateSamplerMapping() // 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); + int count = d3dUniform->getArraySizeProduct(); if (d3dUniform->isReferencedByFragmentShader()) { @@ -707,7 +762,7 @@ void ProgramD3D::updateSamplerMapping() if (samplerIndex < mSamplersPS.size()) { ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + mSamplersPS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i]; } } } @@ -723,15 +778,37 @@ void ProgramD3D::updateSamplerMapping() if (samplerIndex < mSamplersVS.size()) { ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + mSamplersVS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i]; + } + } + } + + if (d3dUniform->isReferencedByComputeShader()) + { + unsigned int firstIndex = d3dUniform->csRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersCS.size()) + { + ASSERT(mSamplersCS[samplerIndex].active); + mSamplersCS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i]; } } } } + + return SamplerMapping::WasDirty; } -LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +gl::LinkResult ProgramD3D::load(const gl::Context *context, + gl::InfoLog &infoLog, + gl::BinaryInputStream *stream) { + // TODO(jmadill): Use Renderer from contextImpl. + reset(); DeviceIdentifier binaryDeviceIdentifier = {0}; @@ -742,20 +819,19 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0) { infoLog << "Invalid program binary, device configuration has changed."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } int compileFlags = stream->readInt<int>(); if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) { infoLog << "Mismatched compilation flags."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } - // TODO(jmadill): replace MAX_VERTEX_ATTRIBS - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + for (int &index : mAttribLocationToD3DSemantic) { - stream->readInt(&mSemanticIndexes[i]); + stream->readInt(&index); } const unsigned int psSamplerCount = stream->readInt<unsigned int>(); @@ -777,27 +853,39 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) mSamplersVS.push_back(sampler); } + const unsigned int csSamplerCount = stream->readInt<unsigned int>(); + for (unsigned int i = 0; i < csSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersCS.push_back(sampler); + } + stream->readInt(&mUsedVertexSamplerRange); stream->readInt(&mUsedPixelSamplerRange); + stream->readInt(&mUsedComputeSamplerRange); const unsigned int uniformCount = stream->readInt<unsigned int>(); if (stream->error()) { infoLog << "Invalid program binary."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } - const auto &linkedUniforms = mData.getUniforms(); + 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, + new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySizes, linkedUniform.isInDefaultBlock()); stream->readInt(&d3dUniform->psRegisterIndex); stream->readInt(&d3dUniform->vsRegisterIndex); + stream->readInt(&d3dUniform->csRegisterIndex); stream->readInt(&d3dUniform->registerCount); stream->readInt(&d3dUniform->registerElement); @@ -808,7 +896,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) if (stream->error()) { infoLog << "Invalid program binary."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } ASSERT(mD3DUniformBlocks.empty()); @@ -817,6 +905,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) D3DUniformBlock uniformBlock; stream->readInt(&uniformBlock.psRegisterIndex); stream->readInt(&uniformBlock.vsRegisterIndex); + stream->readInt(&uniformBlock.csRegisterIndex); mD3DUniformBlocks.push_back(uniformBlock); } @@ -834,11 +923,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readString(&mVertexHLSL); stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), - sizeof(D3DCompilerWorkarounds)); + sizeof(angle::CompilerWorkaroundsD3D)); stream->readString(&mPixelHLSL); stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), - sizeof(D3DCompilerWorkarounds)); + sizeof(angle::CompilerWorkaroundsD3D)); stream->readBool(&mUsesFragDepth); + stream->readBool(&mHasANGLEMultiviewEnabled); + stream->readBool(&mUsesViewID); stream->readBool(&mUsesPointSize); stream->readBool(&mUsesFlatInterpolation); @@ -857,6 +948,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) 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++) @@ -874,18 +967,14 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) ShaderExecutableD3D *shaderExecutable = nullptr; - gl::Error error = mRenderer->loadExecutable( - vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); - if (error.isError()) - { - return LinkResult(false, error); - } + ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, + gl::SHADER_VERTEX, mStreamOutVaryings, separateAttribs, + &shaderExecutable)); if (!shaderExecutable) { infoLog << "Could not create vertex shader."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } // generated converted input layout @@ -893,8 +982,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) VertexExecutable::getSignature(mRenderer, inputLayout, &signature); // add new binary - mVertexExecutables.push_back( - new VertexExecutable(inputLayout, signature, shaderExecutable)); + mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>( + new VertexExecutable(inputLayout, signature, shaderExecutable))); stream->skip(vertexShaderSize); } @@ -913,22 +1002,19 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) const unsigned char *pixelShaderFunction = binary + stream->offset(); ShaderExecutableD3D *shaderExecutable = nullptr; - gl::Error error = mRenderer->loadExecutable( - pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); - if (error.isError()) - { - return LinkResult(false, error); - } + ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, + gl::SHADER_FRAGMENT, mStreamOutVaryings, + separateAttribs, &shaderExecutable)); if (!shaderExecutable) { infoLog << "Could not create pixel shader."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } // add new binary - mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); + mPixelExecutables.push_back( + std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable))); stream->skip(pixelShaderSize); } @@ -939,36 +1025,52 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) unsigned int geometryShaderSize = stream->readInt<unsigned int>(); if (geometryShaderSize == 0) { - mGeometryExecutables[geometryExeIndex] = nullptr; continue; } const unsigned char *geometryShaderFunction = binary + stream->offset(); - bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS); - gl::Error error = mRenderer->loadExecutable( - geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings, - splitAttribs, &mGeometryExecutables[geometryExeIndex]); - if (error.isError()) - { - return LinkResult(false, error); - } + ShaderExecutableD3D *geometryExecutable = nullptr; + ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, + gl::SHADER_GEOMETRY, mStreamOutVaryings, + separateAttribs, &geometryExecutable)); - if (!mGeometryExecutables[geometryExeIndex]) + if (!geometryExecutable) { infoLog << "Could not create geometry shader."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + return false; } + + mGeometryExecutables[geometryExeIndex].reset(geometryExecutable); + stream->skip(geometryShaderSize); } + unsigned int computeShaderSize = stream->readInt<unsigned int>(); + if (computeShaderSize > 0) + { + const unsigned char *computeShaderFunction = binary + stream->offset(); + + ShaderExecutableD3D *computeExecutable = nullptr; + ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize, + gl::SHADER_COMPUTE, std::vector<D3DVarying>(), false, + &computeExecutable)); + + if (!computeExecutable) + { + infoLog << "Could not create compute shader."; + return false; + } + + mComputeExecutable.reset(computeExecutable); + } + initializeUniformStorage(); - initAttributesByLayout(); - return LinkResult(true, gl::Error(GL_NO_ERROR)); + return true; } -gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) +void ProgramD3D::save(const gl::Context *context, 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 @@ -979,10 +1081,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); - // TODO(jmadill): replace MAX_VERTEX_ATTRIBS - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + for (int d3dSemantic : mAttribLocationToD3DSemantic) { - stream->writeInt(mSemanticIndexes[i]); + stream->writeInt(d3dSemantic); } stream->writeInt(mSamplersPS.size()); @@ -1001,15 +1102,25 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(mSamplersVS[i].textureType); } + stream->writeInt(mSamplersCS.size()); + for (unsigned int i = 0; i < mSamplersCS.size(); ++i) + { + stream->writeInt(mSamplersCS[i].active); + stream->writeInt(mSamplersCS[i].logicalTextureUnit); + stream->writeInt(mSamplersCS[i].textureType); + } + stream->writeInt(mUsedVertexSamplerRange); stream->writeInt(mUsedPixelSamplerRange); + stream->writeInt(mUsedComputeSamplerRange); stream->writeInt(mD3DUniforms.size()); for (const D3DUniform *uniform : mD3DUniforms) { // Type, name and arraySize are redundant, so aren't stored in the binary. - stream->writeInt(uniform->psRegisterIndex); - stream->writeInt(uniform->vsRegisterIndex); + stream->writeIntOrNegOne(uniform->psRegisterIndex); + stream->writeIntOrNegOne(uniform->vsRegisterIndex); + stream->writeIntOrNegOne(uniform->csRegisterIndex); stream->writeInt(uniform->registerCount); stream->writeInt(uniform->registerElement); } @@ -1017,8 +1128,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(mD3DUniformBlocks.size()); for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks) { - stream->writeInt(uniformBlock.psRegisterIndex); - stream->writeInt(uniformBlock.vsRegisterIndex); + stream->writeIntOrNegOne(uniformBlock.psRegisterIndex); + stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex); + stream->writeIntOrNegOne(uniformBlock.csRegisterIndex); } stream->writeInt(mStreamOutVaryings.size()); @@ -1032,11 +1144,13 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeString(mVertexHLSL); stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), - sizeof(D3DCompilerWorkarounds)); + sizeof(angle::CompilerWorkaroundsD3D)); stream->writeString(mPixelHLSL); stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), - sizeof(D3DCompilerWorkarounds)); + sizeof(angle::CompilerWorkaroundsD3D)); stream->writeInt(mUsesFragDepth); + stream->writeInt(mHasANGLEMultiviewEnabled); + stream->writeInt(mUsesViewID); stream->writeInt(mUsesPointSize); stream->writeInt(mUsesFlatInterpolation); @@ -1058,14 +1172,14 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) { - VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; + VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get(); const auto &inputLayout = vertexExecutable->inputs(); stream->writeInt(inputLayout.size()); for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++) { - stream->writeInt(inputLayout[inputIndex]); + stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex])); } size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); @@ -1079,7 +1193,7 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) { - PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get(); const std::vector<GLenum> outputs = pixelExecutable->outputSignature(); stream->writeInt(outputs.size()); @@ -1095,150 +1209,120 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeBytes(pixelBlob, pixelShaderSize); } - for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables) + for (auto const &geometryExecutable : mGeometryExecutables) { - if (geometryExe == nullptr) + if (!geometryExecutable) { stream->writeInt(0); continue; } - size_t geometryShaderSize = geometryExe->getLength(); + size_t geometryShaderSize = geometryExecutable->getLength(); stream->writeInt(geometryShaderSize); - stream->writeBytes(geometryExe->getFunction(), geometryShaderSize); + stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize); } - return gl::Error(GL_NO_ERROR); + if (mComputeExecutable) + { + size_t computeShaderSize = mComputeExecutable->getLength(); + stream->writeInt(computeShaderSize); + stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize); + } + else + { + stream->writeInt(0); + } } void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) { } -gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, - ShaderExecutableD3D **outExecutable) +void ProgramD3D::setSeparable(bool /* separable */) { - 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) +gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog) { - for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + if (mCachedPixelExecutableIndex.valid()) { - if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) - { - *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable(); - return gl::Error(GL_NO_ERROR); - } + *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable(); + return gl::NoError(); } std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature( - mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature); + mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache); // Generate new pixel executable - ShaderExecutableD3D *pixelExecutable = NULL; + ShaderExecutableD3D *pixelExecutable = nullptr; gl::InfoLog tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; - gl::Error error = mRenderer->compileToExecutable( - *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, - &pixelExecutable); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->compileToExecutable( + *currentInfoLog, finalPixelHLSL, gl::SHADER_FRAGMENT, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, + &pixelExecutable)); if (pixelExecutable) { - mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>( + new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable))); + mCachedPixelExecutableIndex = mPixelExecutables.size() - 1; } 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]); + ERR() << "Error compiling dynamic pixel executable:" << std::endl + << tempInfoLog.str() << std::endl; } - *outExectuable = pixelExecutable; - return gl::Error(GL_NO_ERROR); + *outExecutable = pixelExecutable; + return gl::NoError(); } -gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, - ShaderExecutableD3D **outExectuable, - gl::InfoLog *infoLog) +gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) { - VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature); - - for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + if (mCachedVertexExecutableIndex.valid()) { - if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature)) - { - *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); - return gl::Error(GL_NO_ERROR); - } + *outExectuable = + mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable(); + return gl::NoError(); } // Generate new dynamic layout with attribute conversions std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout( - mVertexHLSL, inputLayout, mData.getAttributes()); + mVertexHLSL, mCachedInputLayout, mState.getAttributes()); // Generate new vertex executable - ShaderExecutableD3D *vertexExecutable = NULL; + ShaderExecutableD3D *vertexExecutable = nullptr; gl::InfoLog tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; - gl::Error error = mRenderer->compileToExecutable( - *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, - &vertexExecutable); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->compileToExecutable( + *currentInfoLog, finalVertexHLSL, gl::SHADER_VERTEX, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, + &vertexExecutable)); if (vertexExecutable) { - mVertexExecutables.push_back( - new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)); + mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>( + new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable))); + mCachedVertexExecutableIndex = mVertexExecutables.size() - 1; } 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]); + ERR() << "Error compiling dynamic vertex executable:" << std::endl + << tempInfoLog.str() << std::endl; } *outExectuable = vertexExecutable; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data, +gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context, GLenum drawMode, ShaderExecutableD3D **outExecutable, gl::InfoLog *infoLog) @@ -1251,75 +1335,188 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data // Return a null shader if the current rendering doesn't use a geometry shader if (!usesGeometryShader(drawMode)) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode); - if (mGeometryExecutables[geometryShaderType] != nullptr) + if (mGeometryExecutables[geometryShaderType]) { if (outExecutable) { - *outExecutable = mGeometryExecutables[geometryShaderType]; + *outExecutable = mGeometryExecutables[geometryShaderType].get(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL( - geometryShaderType, data, mData, mRenderer->presentPathFastEnabled(), - mGeometryShaderPreamble); + context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(), + mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(), + usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble); gl::InfoLog tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; - gl::Error error = mRenderer->compileToExecutable( - *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(), - &mGeometryExecutables[geometryShaderType]); + ShaderExecutableD3D *geometryExecutable = nullptr; + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, geometryHLSL, gl::SHADER_GEOMETRY, mStreamOutVaryings, + (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), + angle::CompilerWorkaroundsD3D(), &geometryExecutable); 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]); + ERR() << "Error compiling dynamic geometry executable:" << std::endl + << tempInfoLog.str() << std::endl; + } + + if (geometryExecutable != nullptr) + { + mGeometryExecutables[geometryShaderType].reset(geometryExecutable); } if (outExecutable) { - *outExecutable = mGeometryExecutables[geometryShaderType]; + *outExecutable = mGeometryExecutables[geometryShaderType].get(); } return error; } -LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog) +class ProgramD3D::GetExecutableTask : public Closure +{ + public: + GetExecutableTask(ProgramD3D *program) + : mProgram(program), mError(gl::NoError()), mInfoLog(), mResult(nullptr) + { + } + + virtual gl::Error run() = 0; + + void operator()() override { mError = run(); } + + const gl::Error &getError() const { return mError; } + const gl::InfoLog &getInfoLog() const { return mInfoLog; } + ShaderExecutableD3D *getResult() { return mResult; } + + protected: + ProgramD3D *mProgram; + gl::Error mError; + gl::InfoLog mInfoLog; + ShaderExecutableD3D *mResult; +}; + +class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask +{ + public: + GetVertexExecutableTask(ProgramD3D *program, const gl::Context *context) + : GetExecutableTask(program), mContext(context) + { + } + gl::Error run() override + { + mProgram->updateCachedInputLayoutFromShader(mContext); + + ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog)); + + return gl::NoError(); + } + + private: + const gl::Context *mContext; +}; + +void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context) +{ + GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout); + VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature); + updateCachedVertexExecutableIndex(); +} + +class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask +{ + public: + GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {} + gl::Error run() override + { + mProgram->updateCachedOutputLayoutFromShader(); + + ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog)); + + return gl::NoError(); + } +}; + +void ProgramD3D::updateCachedOutputLayoutFromShader() +{ + GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache); + updateCachedPixelExecutableIndex(); +} + +class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask { - const gl::InputLayout &defaultInputLayout = - GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader()); - ShaderExecutableD3D *defaultVertexExecutable = NULL; - gl::Error error = - getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); - if (error.isError()) + public: + GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context) + : GetExecutableTask(program), mContext(context) { - return LinkResult(false, error); } - std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); - ShaderExecutableD3D *defaultPixelExecutable = NULL; - error = - getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); - if (error.isError()) + gl::Error run() override { - return LinkResult(false, error); + // Auto-generate the geometry shader here, if we expect to be using point rendering in + // D3D11. + if (mProgram->usesGeometryShader(GL_POINTS)) + { + ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContext, GL_POINTS, &mResult, + &mInfoLog)); + } + + return gl::NoError(); } - // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11. - ShaderExecutableD3D *pointGS = nullptr; - if (usesGeometryShader(GL_POINTS)) + private: + const gl::Context *mContext; +}; + +gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable) +{ + if (outExecutable) { - getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog); + *outExecutable = mComputeExecutable.get(); } - const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader()); + return gl::NoError(); +} + +gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context, + gl::InfoLog &infoLog) +{ + // Ensure the compiler is initialized to avoid race conditions. + ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized()); + + WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool(); + + GetVertexExecutableTask vertexTask(this, context); + GetPixelExecutableTask pixelTask(this); + GetGeometryExecutableTask geometryTask(this, context); + + std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask), + workerPool->postWorkerTask(&pixelTask), + workerPool->postWorkerTask(&geometryTask)}}; + + WaitableEvent::WaitMany(&waitEvents); + + infoLog << vertexTask.getInfoLog().str(); + infoLog << pixelTask.getInfoLog().str(); + infoLog << geometryTask.getInfoLog().str(); + + ANGLE_TRY(vertexTask.getError()); + ANGLE_TRY(pixelTask.getError()); + ANGLE_TRY(geometryTask.getError()); + + ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult(); + ShaderExecutableD3D *defaultPixelExecutable = pixelTask.getResult(); + ShaderExecutableD3D *pointGS = geometryTask.getResult(); + + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); if (usesGeometryShader(GL_POINTS) && pointGS) { @@ -1339,128 +1536,148 @@ LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoL if (defaultPixelExecutable) { const ShaderD3D *fragmentShaderD3D = - GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader()); + GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); } - bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && - (!usesGeometryShader(GL_POINTS) || pointGS)); - return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); + return (defaultVertexExecutable && defaultPixelExecutable && + (!usesGeometryShader(GL_POINTS) || pointGS)); } -LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) +gl::LinkResult ProgramD3D::compileComputeExecutable(const gl::Context *context, + gl::InfoLog &infoLog) { - reset(); + // Ensure the compiler is initialized to avoid race conditions. + ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized()); + + std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(context, mState); - // TODO(jmadill): structures containing samplers - for (const gl::LinkedUniform &linkedUniform : mData.getUniforms()) + ShaderExecutableD3D *computeExecutable = nullptr; + ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, gl::SHADER_COMPUTE, + std::vector<D3DVarying>(), false, + angle::CompilerWorkaroundsD3D(), &computeExecutable)); + + if (computeExecutable == nullptr) { - if (linkedUniform.isSampler() && linkedUniform.isField()) - { - infoLog << "Structures containing samplers not currently supported in D3D."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + ERR() << "Error compiling dynamic compute executable:" << std::endl + << infoLog.str() << std::endl; + } + else + { + const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader()); + computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo()); + mComputeExecutable.reset(computeExecutable); } - const gl::Shader *vertexShader = mData.getAttachedVertexShader(); - const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); - - const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader); - const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader); + return mComputeExecutable.get() != nullptr; +} - mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); - mSamplersPS.resize(data.caps->maxTextureImageUnits); +gl::LinkResult ProgramD3D::link(const gl::Context *context, + const gl::ProgramLinkedResources &resources, + gl::InfoLog &infoLog) +{ + const auto &data = context->getContextState(); - vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); - fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); + reset(); - if (mRenderer->getRendererLimitations().noFrontFacingSupport) + gl::Shader *computeShader = mState.getAttachedComputeShader(); + if (computeShader) { - if (fragmentShaderD3D->usesFrontFacing()) + mSamplersCS.resize(data.getCaps().maxComputeTextureImageUnits); + + defineUniformsAndAssignRegisters(context); + + gl::LinkResult result = compileComputeExecutable(context, infoLog); + if (result.isError()) { - infoLog << "The current renderer doesn't support gl_FrontFacing"; - return LinkResult(false, gl::Error(GL_NO_ERROR)); + infoLog << result.getError().getMessage(); + return result; + } + else if (!result.getResult()) + { + infoLog << "Failed to create D3D compute shader."; + return result; } } + else + { + gl::Shader *vertexShader = mState.getAttachedVertexShader(); + gl::Shader *fragmentShader = mState.getAttachedFragmentShader(); - std::vector<PackedVarying> packedVaryings = - MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames()); + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader); + const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader); - // Map the varyings to the register file - VaryingPacking varyingPacking(data.caps->maxVaryingVectors); - if (!varyingPacking.packVaryings(infoLog, packedVaryings, - mData.getTransformFeedbackVaryingNames())) - { - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits); + mSamplersPS.resize(data.getCaps().maxTextureImageUnits); - ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(), - usesInstancedPointSpriteEmulation(), - mRenderer->presentPathFastEnabled(), vertexShaderD3D, - fragmentShaderD3D); + vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); + fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); - varyingPacking.enableBuiltins(SHADER_VERTEX, metadata); - varyingPacking.enableBuiltins(SHADER_PIXEL, metadata); + if (mRenderer->getNativeLimitations().noFrontFacingSupport) + { + if (fragmentShaderD3D->usesFrontFacing()) + { + infoLog << "The current renderer doesn't support gl_FrontFacing"; + return false; + } + } - if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors) - { - infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord"; - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + // 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 && + resources.varyingPacking.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors) + { + infoLog << "Cannot pack these varyings on D3D9."; + 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.caps->maxVaryingVectors) - { - infoLog << "Cannot pack these varyings on D3D9."; - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D); + BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking); - if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL, - &mVertexHLSL)) - { - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + mDynamicHLSL->generateShaderLinkHLSL(context, mState, metadata, resources.varyingPacking, + builtins, &mPixelHLSL, &mVertexHLSL); - mUsesPointSize = vertexShaderD3D->usesPointSize(); - mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey); - mUsesFragDepth = metadata.usesFragDepth(mData); + mUsesPointSize = vertexShaderD3D->usesPointSize(); + mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey); + mUsesFragDepth = metadata.usesFragDepth(); + mUsesViewID = metadata.usesViewID(); + mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled(); - // Cache if we use flat shading - mUsesFlatInterpolation = false; - for (const auto &varying : packedVaryings) - { - if (varying.interpolation == sh::INTERPOLATION_FLAT) + // Cache if we use flat shading + mUsesFlatInterpolation = + (FindFlatInterpolationVarying(fragmentShader->getInputVaryings(context)) || + FindFlatInterpolationVarying(vertexShader->getOutputVaryings(context))); + + if (mRenderer->getMajorShaderModel() >= 4) { - mUsesFlatInterpolation = true; - break; + mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble( + resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled, + metadata.canSelectViewInVertexShader()); } - } - if (mRenderer->getMajorShaderModel() >= 4) - { - varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata); - mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking); - } + initAttribLocationsToD3DSemantic(context); - initSemanticIndex(); + defineUniformsAndAssignRegisters(context); - defineUniformsAndAssignRegisters(); + gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::SHADER_VERTEX]); - gatherTransformFeedbackVaryings(varyingPacking); - - LinkResult result = compileProgramExecutables(data, infoLog); - if (result.error.isError() || !result.linkSuccess) - { - infoLog << "Failed to create D3D shaders."; - return result; + gl::LinkResult result = compileProgramExecutables(context, infoLog); + if (result.isError()) + { + infoLog << result.getError().getMessage(); + return result; + } + else if (!result.getResult()) + { + infoLog << "Failed to create D3D shaders."; + return result; + } } - initUniformBlockInfo(); + linkResources(context, resources); - return LinkResult(true, gl::Error(GL_NO_ERROR)); + return true; } GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/) @@ -1469,46 +1686,22 @@ GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLo return GL_TRUE; } -void ProgramD3D::initUniformBlockInfo() +void ProgramD3D::initializeUniformBlocks() { - const gl::Shader *vertexShader = mData.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 = mData.getAttachedFragmentShader(); - - for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks()) + if (mState.getUniformBlocks().empty()) { - 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; + return; } -} -void ProgramD3D::assignUniformBlockRegisters() -{ - mD3DUniformBlocks.clear(); + ASSERT(mD3DUniformBlocks.empty()); // Assign registers and update sizes. - const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader()); - const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader()); + const ShaderD3D *vertexShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = + SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); + const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader()); - for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks()) + for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks()) { unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0; @@ -1516,18 +1709,27 @@ void ProgramD3D::assignUniformBlockRegisters() if (uniformBlock.vertexStaticUse) { - unsigned int baseRegister = - vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + ASSERT(vertexShaderD3D != nullptr); + unsigned int baseRegister = vertexShaderD3D->getUniformBlockRegister(uniformBlock.name); d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement; } if (uniformBlock.fragmentStaticUse) { + ASSERT(fragmentShaderD3D != nullptr); unsigned int baseRegister = - fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + fragmentShaderD3D->getUniformBlockRegister(uniformBlock.name); d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement; } + if (uniformBlock.computeStaticUse) + { + ASSERT(computeShaderD3D != nullptr); + unsigned int baseRegister = + computeShaderD3D->getUniformBlockRegister(uniformBlock.name); + d3dUniformBlock.csRegisterIndex = baseRegister + uniformBlockElement; + } + mD3DUniformBlocks.push_back(d3dUniformBlock); } } @@ -1537,6 +1739,7 @@ void ProgramD3D::initializeUniformStorage() // Compute total default block size unsigned int vertexRegisters = 0; unsigned int fragmentRegisters = 0; + unsigned int computeRegisters = 0; for (const D3DUniform *d3dUniform : mD3DUniforms) { if (!d3dUniform->isSampler()) @@ -1551,55 +1754,67 @@ void ProgramD3D::initializeUniformStorage() fragmentRegisters = std::max( fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount); } + if (d3dUniform->isReferencedByComputeShader()) + { + computeRegisters = std::max( + computeRegisters, d3dUniform->csRegisterIndex + 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; - } + mVertexUniformStorage = + std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(vertexRegisters * 16u)); + mFragmentUniformStorage = std::unique_ptr<UniformStorageD3D>( + mRenderer->createUniformStorage(fragmentRegisters * 16u)); + mComputeUniformStorage = + std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(computeRegisters * 16u)); + // Iterate the uniforms again to assign data pointers to default block uniforms. for (D3DUniform *d3dUniform : mD3DUniforms) { - d3dUniform->dirty = false; - } + if (d3dUniform->isSampler()) + { + d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0); + continue; + } - return gl::Error(GL_NO_ERROR); -} + if (d3dUniform->isReferencedByVertexShader()) + { + d3dUniform->vsData = mVertexUniformStorage->getDataPointer(d3dUniform->vsRegisterIndex, + d3dUniform->registerElement); + } -gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) -{ - if (mData.getUniformBlocks().empty()) - { - return gl::Error(GL_NO_ERROR); + if (d3dUniform->isReferencedByFragmentShader()) + { + d3dUniform->psData = mFragmentUniformStorage->getDataPointer( + d3dUniform->psRegisterIndex, d3dUniform->registerElement); + } + + if (d3dUniform->isReferencedByComputeShader()) + { + d3dUniform->csData = mComputeUniformStorage->getDataPointer( + d3dUniform->csRegisterIndex, d3dUniform->registerElement); + } } +} - // Lazy init. - if (mD3DUniformBlocks.empty()) +void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps, + unsigned int reservedVertex, + unsigned int reservedFragment) +{ + if (mState.getUniformBlocks().empty()) { - assignUniformBlockRegisters(); + return; } 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 = mData.getUniformBlockBinding(uniformBlockIndex); + GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex); // Unnecessary to apply an unreferenced standard or shared UBO if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse()) @@ -1609,8 +1824,8 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) if (uniformBlock.vertexStaticUse()) { - unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS; - ASSERT(registerIndex < data.caps->maxVertexUniformBlocks); + unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedVertex; + ASSERT(registerIndex < caps.maxVertexUniformBlocks); if (mVertexUBOCache.size() <= registerIndex) { @@ -1623,8 +1838,8 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) if (uniformBlock.fragmentStaticUse()) { - unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS; - ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks); + unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedFragment; + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); if (mFragmentUBOCache.size() <= registerIndex) { @@ -1635,36 +1850,50 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) mFragmentUBOCache[registerIndex] = blockBinding; } } +} - return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache); +const std::vector<GLint> &ProgramD3D::getVertexUniformBufferCache() const +{ + return mVertexUBOCache; +} + +const std::vector<GLint> &ProgramD3D::getFragmentUniformBufferCache() const +{ + return mFragmentUBOCache; } void ProgramD3D::dirtyAllUniforms() { - for (D3DUniform *d3dUniform : mD3DUniforms) - { - d3dUniform->dirty = true; - } + mVertexUniformsDirty = true; + mFragmentUniformsDirty = true; + mComputeUniformsDirty = true; +} + +void ProgramD3D::markUniformsClean() +{ + mVertexUniformsDirty = false; + mFragmentUniformsDirty = false; + mComputeUniformsDirty = false; } void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { - setUniform(location, count, v, GL_FLOAT); + setUniformInternal(location, count, v, GL_FLOAT); } void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { - setUniform(location, count, v, GL_FLOAT_VEC2); + setUniformInternal(location, count, v, GL_FLOAT_VEC2); } void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { - setUniform(location, count, v, GL_FLOAT_VEC3); + setUniformInternal(location, count, v, GL_FLOAT_VEC3); } void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { - setUniform(location, count, v, GL_FLOAT_VEC4); + setUniformInternal(location, count, v, GL_FLOAT_VEC4); } void ProgramD3D::setUniformMatrix2fv(GLint location, @@ -1672,7 +1901,7 @@ void ProgramD3D::setUniformMatrix2fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); + setUniformMatrixfvInternal<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); } void ProgramD3D::setUniformMatrix3fv(GLint location, @@ -1680,7 +1909,7 @@ void ProgramD3D::setUniformMatrix3fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); + setUniformMatrixfvInternal<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); } void ProgramD3D::setUniformMatrix4fv(GLint location, @@ -1688,7 +1917,7 @@ void ProgramD3D::setUniformMatrix4fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); + setUniformMatrixfvInternal<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); } void ProgramD3D::setUniformMatrix2x3fv(GLint location, @@ -1696,7 +1925,7 @@ void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); + setUniformMatrixfvInternal<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); } void ProgramD3D::setUniformMatrix3x2fv(GLint location, @@ -1704,7 +1933,7 @@ void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); + setUniformMatrixfvInternal<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); } void ProgramD3D::setUniformMatrix2x4fv(GLint location, @@ -1712,7 +1941,7 @@ void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); + setUniformMatrixfvInternal<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); } void ProgramD3D::setUniformMatrix4x2fv(GLint location, @@ -1720,7 +1949,7 @@ void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); + setUniformMatrixfvInternal<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); } void ProgramD3D::setUniformMatrix3x4fv(GLint location, @@ -1728,7 +1957,7 @@ void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); + setUniformMatrixfvInternal<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); } void ProgramD3D::setUniformMatrix4x3fv(GLint location, @@ -1736,47 +1965,47 @@ void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLboolean transpose, const GLfloat *value) { - setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); + setUniformMatrixfvInternal<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); + setUniformInternal(location, count, v, GL_INT); } void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v) { - setUniform(location, count, v, GL_INT_VEC2); + setUniformInternal(location, count, v, GL_INT_VEC2); } void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v) { - setUniform(location, count, v, GL_INT_VEC3); + setUniformInternal(location, count, v, GL_INT_VEC3); } void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v) { - setUniform(location, count, v, GL_INT_VEC4); + setUniformInternal(location, count, v, GL_INT_VEC4); } void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { - setUniform(location, count, v, GL_UNSIGNED_INT); + setUniformInternal(location, count, v, GL_UNSIGNED_INT); } void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { - setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); + setUniformInternal(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); + setUniformInternal(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); + setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4); } void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, @@ -1784,35 +2013,58 @@ void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, { } -void ProgramD3D::defineUniformsAndAssignRegisters() +void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context) { D3DUniformMap uniformMap; - const gl::Shader *vertexShader = mData.getAttachedVertexShader(); - for (const sh::Uniform &vertexUniform : vertexShader->getUniforms()) - + gl::Shader *computeShader = mState.getAttachedComputeShader(); + if (computeShader) { - if (vertexUniform.staticUse) + for (const sh::Uniform &computeUniform : computeShader->getUniforms(context)) { - defineUniformBase(vertexShader, vertexUniform, &uniformMap); + if (computeUniform.staticUse) + { + defineUniformBase(computeShader, computeUniform, &uniformMap); + } } } - - const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); - for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms()) + else { - if (fragmentUniform.staticUse) + gl::Shader *vertexShader = mState.getAttachedVertexShader(); + for (const sh::Uniform &vertexUniform : vertexShader->getUniforms(context)) + { + if (vertexUniform.staticUse) + { + defineUniformBase(vertexShader, vertexUniform, &uniformMap); + } + } + + gl::Shader *fragmentShader = mState.getAttachedFragmentShader(); + for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms(context)) { - defineUniformBase(fragmentShader, fragmentUniform, &uniformMap); + if (fragmentUniform.staticUse) + { + defineUniformBase(fragmentShader, fragmentUniform, &uniformMap); + } } } // Initialize the D3DUniform list to mirror the indexing of the GL layer. - for (const gl::LinkedUniform &glUniform : mData.getUniforms()) + for (const gl::LinkedUniform &glUniform : mState.getUniforms()) { if (!glUniform.isInDefaultBlock()) continue; - auto mapEntry = uniformMap.find(glUniform.name); + std::string name = glUniform.name; + if (glUniform.isArray()) + { + // In the program state, array uniform names include [0] as in the program resource + // spec. Here we don't include it. + // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL + // layer. + ASSERT(angle::EndsWith(name, "[0]")); + name.resize(name.length() - 3); + } + auto mapEntry = uniformMap.find(name); ASSERT(mapEntry != uniformMap.end()); mD3DUniforms.push_back(mapEntry->second); } @@ -1825,7 +2077,8 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader, const sh::Uniform &uniform, D3DUniformMap *uniformMap) { - if (uniform.isBuiltIn()) + // Samplers get their registers assigned in assignAllSamplerRegisters. + if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type)) { defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap); return; @@ -1835,7 +2088,7 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader, unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name); ShShaderOutput outputType = shaderD3D->getCompilerOutputType(); - sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); + sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true); encoder.skipRegisters(startRegister); defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap); @@ -1854,6 +2107,84 @@ D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name) return nullptr; } +void ProgramD3D::defineStructUniformFields(GLenum shaderType, + const std::vector<sh::ShaderVariable> &fields, + const std::string &namePrefix, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap) +{ + if (encoder) + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = fields[fieldIndex]; + const std::string &fieldFullName = (namePrefix + "." + 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(); +} + +void ProgramD3D::defineArrayOfStructsUniformFields(GLenum shaderType, + const sh::ShaderVariable &uniform, + unsigned int arrayNestingIndex, + const std::string &prefix, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap) +{ + // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the + // innermost. + const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex); + for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) + { + const std::string &elementString = prefix + ArrayString(arrayElement); + if (arrayNestingIndex + 1u < uniform.arraySizes.size()) + { + defineArrayOfStructsUniformFields(shaderType, uniform, arrayNestingIndex + 1u, + elementString, encoder, uniformMap); + } + else + { + defineStructUniformFields(shaderType, uniform.fields, elementString, encoder, + uniformMap); + } + } +} + +void ProgramD3D::defineArrayUniformElements(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap) +{ + if (encoder) + encoder->enterAggregateType(); + + sh::ShaderVariable uniformElement = uniform; + uniformElement.arraySizes.pop_back(); + for (unsigned int arrayIndex = 0u; arrayIndex < uniform.getOutermostArraySize(); ++arrayIndex) + { + std::string elementFullName = fullName + ArrayString(arrayIndex); + defineUniform(shaderType, uniformElement, elementFullName, encoder, uniformMap); + } + + if (encoder) + encoder->exitAggregateType(); +} + void ProgramD3D::defineUniform(GLenum shaderType, const sh::ShaderVariable &uniform, const std::string &fullName, @@ -1862,24 +2193,20 @@ void ProgramD3D::defineUniform(GLenum shaderType, { if (uniform.isStruct()) { - for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + if (uniform.isArray()) { - 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); - - defineUniform(shaderType, field, fieldFullName, encoder, uniformMap); - } - - if (encoder) - encoder->exitAggregateType(); + defineArrayOfStructsUniformFields(shaderType, uniform, 0u, fullName, encoder, + uniformMap); } + else + { + defineStructUniformFields(shaderType, uniform.fields, fullName, encoder, uniformMap); + } + return; + } + if (uniform.isArrayOfArrays()) + { + defineArrayUniformElements(shaderType, uniform, fullName, encoder, uniformMap); return; } @@ -1891,7 +2218,7 @@ void ProgramD3D::defineUniform(GLenum shaderType, // Advance the uniform offset, to track registers allocation for structs sh::BlockMemberInfo blockInfo = - encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false) + encoder ? encoder->encodeType(uniform.type, uniform.arraySizes, false) : sh::BlockMemberInfo::getDefaultBlockInfo(); auto uniformMapEntry = uniformMap->find(fullName); @@ -1903,7 +2230,7 @@ void ProgramD3D::defineUniform(GLenum shaderType, } else { - d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true); + d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySizes, true); (*uniformMap)[fullName] = d3dUniform; } @@ -1917,11 +2244,15 @@ void ProgramD3D::defineUniform(GLenum shaderType, { d3dUniform->psRegisterIndex = reg; } - else + else if (shaderType == GL_VERTEX_SHADER) { - ASSERT(shaderType == GL_VERTEX_SHADER); d3dUniform->vsRegisterIndex = reg; } + else + { + ASSERT(shaderType == GL_COMPUTE_SHADER); + d3dUniform->csRegisterIndex = reg; + } // Arrays are treated as aggregate types if (uniform.isArray()) @@ -1931,177 +2262,223 @@ void ProgramD3D::defineUniform(GLenum shaderType, } } +// Assume count is already clamped. template <typename T> -void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType) +void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo, + GLsizei count, + const T *v, + uint8_t *targetData, + GLenum uniformType) { - const int components = gl::VariableComponentCount(targetUniformType); - const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); - - D3DUniform *targetUniform = getD3DUniformFromLocation(location); + D3DUniform *targetUniform = mD3DUniforms[locationInfo.index]; + const int components = targetUniform->typeInfo.componentCount; + const unsigned int arrayElementOffset = locationInfo.arrayIndex; - unsigned int elementCount = targetUniform->elementCount(); - unsigned int arrayElement = mData.getUniformLocations()[location].element; - unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn)); - - if (targetUniform->type == targetUniformType) + if (targetUniform->typeInfo.type == uniformType) { - T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4; + T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4; + const T *source = v; - for (unsigned int i = 0; i < count; i++) + for (GLint i = 0; i < count; i++, dest += 4, source += components) { - 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); - } + memcpy(dest, source, components * sizeof(T)); } } - else if (targetUniform->type == targetBoolType) + else { - GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4; + ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType)); + GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4; - for (unsigned int i = 0; i < count; i++) + for (GLint 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); + dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE; } } } - 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); - } +template <typename T> +void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType) +{ + const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location]; + D3DUniform *targetUniform = mD3DUniforms[locationInfo.index]; - if (!wasDirty && targetUniform->dirty) + if (targetUniform->typeInfo.isSampler) + { + ASSERT(uniformType == GL_INT); + size_t size = count * sizeof(T); + GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex]; + if (memcmp(dest, v, size) != 0) { + memcpy(dest, v, size); mDirtySamplerMapping = true; } + return; + } + + if (targetUniform->vsData) + { + setUniformImpl(locationInfo, count, v, targetUniform->vsData, uniformType); + mVertexUniformsDirty = true; + } + + if (targetUniform->psData) + { + setUniformImpl(locationInfo, count, v, targetUniform->psData, uniformType); + mFragmentUniformsDirty = true; + } + + if (targetUniform->csData) + { + setUniformImpl(locationInfo, count, v, targetUniform->csData, uniformType); + mComputeUniformsDirty = true; } - else - UNREACHABLE(); } template <int cols, int rows> -void ProgramD3D::setUniformMatrixfv(GLint location, - GLsizei countIn, - GLboolean transpose, - const GLfloat *value, - GLenum targetUniformType) +bool ProgramD3D::setUniformMatrixfvImpl(GLint location, + GLsizei countIn, + GLboolean transpose, + const GLfloat *value, + uint8_t *targetData, + GLenum targetUniformType) { D3DUniform *targetUniform = getD3DUniformFromLocation(location); - unsigned int elementCount = targetUniform->elementCount(); - unsigned int arrayElement = mData.getUniformLocations()[location].element; - unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn)); + unsigned int elementCount = targetUniform->getArraySizeProduct(); + unsigned int arrayElementOffset = mState.getUniformLocations()[location].arrayIndex; + unsigned int count = + std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn)); const unsigned int targetMatrixStride = (4 * rows); - GLfloat *target = - (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride); + GLfloat *target = reinterpret_cast<GLfloat *>( + targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride); + + bool dirty = false; 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; + dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty; } else { - targetUniform->dirty = - ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty; + dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty; } target += targetMatrixStride; value += cols * rows; } + + return dirty; } -size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock) +template <int cols, int rows> +void ProgramD3D::setUniformMatrixfvInternal(GLint location, + GLsizei countIn, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType) { - 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; + D3DUniform *targetUniform = getD3DUniformFromLocation(location); - if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + if (targetUniform->vsData) { - encoder = &std140Encoder; + if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value, + targetUniform->vsData, targetUniformType)) + { + mVertexUniformsDirty = true; + } } - else + + if (targetUniform->psData) { - encoder = &hlslEncoder; + if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value, + targetUniform->psData, targetUniformType)) + { + mFragmentUniformsDirty = true; + } } - GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, - interfaceBlock.isRowMajorLayout, &mBlockInfo); - - return encoder->getBlockSize(); + if (targetUniform->csData) + { + if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value, + targetUniform->csData, targetUniformType)) + { + mComputeUniformsDirty = true; + } + } } void ProgramD3D::assignAllSamplerRegisters() { - for (const D3DUniform *d3dUniform : mD3DUniforms) + for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex) { - if (d3dUniform->isSampler()) + if (mD3DUniforms[uniformIndex]->isSampler()) { - assignSamplerRegisters(d3dUniform); + assignSamplerRegisters(uniformIndex); } } } -void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform) +void ProgramD3D::assignSamplerRegisters(size_t uniformIndex) { + D3DUniform *d3dUniform = mD3DUniforms[uniformIndex]; ASSERT(d3dUniform->isSampler()); - ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX || - d3dUniform->psRegisterIndex != GL_INVALID_INDEX); - - if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX) - { - AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize, - mSamplersVS, &mUsedVertexSamplerRange); + // If the uniform is an array of arrays, then we have separate entries for each inner array in + // mD3DUniforms. However, the sampler register info is stored in the shader only for the + // outermost array. + std::vector<unsigned int> subscripts; + const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts); + unsigned int registerOffset = mState.getUniforms()[uniformIndex].flattenedOffsetInParentArrays * + d3dUniform->getArraySizeProduct(); + + const gl::Shader *computeShader = mState.getAttachedComputeShader(); + if (computeShader) + { + const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader()); + ASSERT(computeShaderD3D->hasUniform(baseName)); + d3dUniform->csRegisterIndex = + computeShaderD3D->getUniformRegister(baseName) + registerOffset; + ASSERT(d3dUniform->csRegisterIndex != GL_INVALID_INDEX); + AssignSamplers(d3dUniform->csRegisterIndex, d3dUniform->typeInfo, + d3dUniform->getArraySizeProduct(), mSamplersCS, &mUsedComputeSamplerRange); } - - if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX) + else { - AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize, - mSamplersPS, &mUsedPixelSamplerRange); + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = + GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); + ASSERT(vertexShaderD3D->hasUniform(baseName) || fragmentShaderD3D->hasUniform(baseName)); + if (vertexShaderD3D->hasUniform(baseName)) + { + d3dUniform->vsRegisterIndex = + vertexShaderD3D->getUniformRegister(baseName) + registerOffset; + ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX); + AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->typeInfo, + d3dUniform->getArraySizeProduct(), mSamplersVS, + &mUsedVertexSamplerRange); + } + if (fragmentShaderD3D->hasUniform(baseName)) + { + d3dUniform->psRegisterIndex = + fragmentShaderD3D->getUniformRegister(baseName) + registerOffset; + ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX); + AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->typeInfo, + d3dUniform->getArraySizeProduct(), mSamplersPS, &mUsedPixelSamplerRange); + } } } // static void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, + const gl::UniformTypeInfo &typeInfo, unsigned int samplerCount, std::vector<Sampler> &outSamplers, GLuint *outUsedRange) @@ -2113,7 +2490,7 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex, ASSERT(samplerIndex < outSamplers.size()); Sampler *sampler = &outSamplers[samplerIndex]; sampler->active = true; - sampler->textureType = gl::SamplerTypeToTextureType(samplerType); + sampler->textureType = typeInfo.samplerTextureType; sampler->logicalTextureUnit = 0; *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); samplerIndex++; @@ -2122,20 +2499,24 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex, void ProgramD3D::reset() { - SafeDeleteContainer(mVertexExecutables); - SafeDeleteContainer(mPixelExecutables); + mVertexExecutables.clear(); + mPixelExecutables.clear(); - for (auto &element : mGeometryExecutables) + for (auto &geometryExecutable : mGeometryExecutables) { - SafeDelete(element); + geometryExecutable.reset(nullptr); } + mComputeExecutable.reset(nullptr); + mVertexHLSL.clear(); - mVertexWorkarounds = D3DCompilerWorkarounds(); + mVertexWorkarounds = angle::CompilerWorkaroundsD3D(); mPixelHLSL.clear(); - mPixelWorkarounds = D3DCompilerWorkarounds(); + mPixelWorkarounds = angle::CompilerWorkaroundsD3D(); mUsesFragDepth = false; + mHasANGLEMultiviewEnabled = false; + mUsesViewID = false; mPixelShaderKey.clear(); mUsesPointSize = false; mUsesFlatInterpolation = false; @@ -2143,22 +2524,29 @@ void ProgramD3D::reset() SafeDeleteContainer(mD3DUniforms); mD3DUniformBlocks.clear(); - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); + mVertexUniformStorage.reset(nullptr); + mFragmentUniformStorage.reset(nullptr); + mComputeUniformStorage.reset(nullptr); mSamplersPS.clear(); mSamplersVS.clear(); + mSamplersCS.clear(); mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; + mUsedComputeSamplerRange = 0; mDirtySamplerMapping = true; - std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1); - std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); + mAttribLocationToD3DSemantic.fill(-1); mStreamOutVaryings.clear(); mGeometryShaderPreamble.clear(); + + dirtyAllUniforms(); + + mCachedPixelExecutableIndex.reset(); + mCachedVertexExecutableIndex.reset(); } unsigned int ProgramD3D::getSerial() const @@ -2171,84 +2559,96 @@ unsigned int ProgramD3D::issueSerial() return mCurrentSerial++; } -void ProgramD3D::initSemanticIndex() +void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context) { - const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + gl::Shader *vertexShader = mState.getAttachedVertexShader(); ASSERT(vertexShader != nullptr); // Init semantic index - for (const sh::Attribute &attribute : mData.getAttributes()) + int semanticIndex = 0; + for (const sh::Attribute &attribute : vertexShader->getActiveAttributes(context)) { - int attributeIndex = attribute.location; - int index = vertexShader->getSemanticIndex(attribute.name); - int regs = gl::VariableRegisterCount(attribute.type); + int regCount = gl::VariableRegisterCount(attribute.type); + GLuint location = mState.getAttributeLocation(attribute.name); + ASSERT(location != std::numeric_limits<GLuint>::max()); - for (int reg = 0; reg < regs; ++reg) + for (int reg = 0; reg < regCount; ++reg) { - mSemanticIndexes[attributeIndex + reg] = index + reg; + mAttribLocationToD3DSemantic[location + reg] = semanticIndex++; } } - - initAttributesByLayout(); } -void ProgramD3D::initAttributesByLayout() +void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state) { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + if (mCurrentVertexArrayStateSerial == associatedSerial) { - mAttributesByLayout[i] = i; + return; } - std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], - AttributeSorter(mSemanticIndexes)); -} + mCurrentVertexArrayStateSerial = associatedSerial; + mCachedInputLayout.clear(); -void ProgramD3D::sortAttributesByLayout( - const std::vector<TranslatedAttribute> &unsortedAttributes, - int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], - const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const -{ - for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex) + const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + + for (size_t locationIndex : mState.getActiveAttribLocationsMask()) { - int oldIndex = mAttributesByLayout[attribIndex]; - sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex]; - sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex]; + 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); + } } + + VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature); + + updateCachedVertexExecutableIndex(); } -void ProgramD3D::updateCachedInputLayout(const gl::State &state) +void ProgramD3D::updateCachedOutputLayout(const gl::Context *context, + const gl::Framebuffer *framebuffer) { - mCachedInputLayout.clear(); - const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + mPixelShaderOutputLayoutCache.clear(); + + FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer); + const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context); - for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask())) + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - int semanticIndex = mSemanticIndexes[attributeIndex]; + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - if (semanticIndex != -1) + if (colorbuffer) { - if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1)) - { - mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID); - } - mCachedInputLayout[semanticIndex] = - GetVertexFormatType(vertexAttributes[attributeIndex], - state.getVertexAttribCurrentValue(attributeIndex).Type); + auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 + : colorbuffer->getBinding(); + mPixelShaderOutputLayoutCache.push_back(binding); + } + else + { + mPixelShaderOutputLayoutCache.push_back(GL_NONE); } } + + updateCachedPixelExecutableIndex(); } -void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking) +void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking, + const BuiltinInfo &builtins) { - 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 = mData.getTransformFeedbackVaryingNames(); + const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames(); for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size()); ++outputSlot) { @@ -2278,7 +2678,14 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa } else { - for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + std::vector<unsigned int> subscripts; + std::string baseName = gl::ParseResourceName(tfVaryingName, &subscripts); + size_t subscript = GL_INVALID_INDEX; + if (!subscripts.empty()) + { + subscript = subscripts.back(); + } + for (const auto ®isterInfo : varyingPacking.getRegisterList()) { const auto &varying = *registerInfo.packedVarying->varying; GLenum transposedType = gl::TransposeMatrixType(varying.type); @@ -2293,7 +2700,8 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa // 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) + if (baseName == registerInfo.packedVarying->varying->name && + (subscript == GL_INVALID_INDEX || subscript == registerInfo.varyingArrayIndex)) { mStreamOutVaryings.push_back(D3DVarying( varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot)); @@ -2305,36 +2713,155 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) { - return mD3DUniforms[mData.getUniformLocations()[location].index]; + return mD3DUniforms[mState.getUniformLocations()[location].index]; +} + +const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const +{ + return mD3DUniforms[mState.getUniformLocations()[location].index]; +} + +void ProgramD3D::setPathFragmentInputGen(const std::string &inputName, + GLenum genMode, + GLint components, + const GLfloat *coeffs) +{ + UNREACHABLE(); } -bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const +bool ProgramD3D::hasVertexExecutableForCachedInputLayout() { - std::string baseName = blockName; - gl::ParseAndStripArrayIndex(&baseName); + return mCachedVertexExecutableIndex.valid(); +} - auto sizeIter = mBlockDataSizes.find(baseName); - if (sizeIter == mBlockDataSizes.end()) +bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode) +{ + if (!usesGeometryShader(drawMode)) { - *sizeOut = 0; - return false; + // No shader necessary mean we have the required (null) executable. + return true; } - *sizeOut = sizeIter->second; - return true; + gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode); + return mGeometryExecutables[geometryShaderType].get() != nullptr; +} + +bool ProgramD3D::hasPixelExecutableForCachedOutputLayout() +{ + return mCachedPixelExecutableIndex.valid(); } -bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName, - sh::BlockMemberInfo *memberInfoOut) const +template <typename DestT> +void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const { - auto infoIter = mBlockInfo.find(memberUniformName); - if (infoIter == mBlockInfo.end()) + const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location]; + const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index]; + + const D3DUniform *targetUniform = getD3DUniformFromLocation(location); + const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex); + + if (gl::IsMatrixType(uniform.type)) { - *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); - return false; + GetMatrixUniform(gl::VariableColumnCount(uniform.type), gl::VariableRowCount(uniform.type), + dataOut, reinterpret_cast<const DestT *>(srcPointer)); } + else + { + memcpy(dataOut, srcPointer, uniform.getElementSize()); + } +} - *memberInfoOut = infoIter->second; - return true; +void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const +{ + getUniformInternal(location, params); +} + +void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const +{ + getUniformInternal(location, params); +} + +void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const +{ + getUniformInternal(location, params); +} + +void ProgramD3D::updateCachedVertexExecutableIndex() +{ + mCachedVertexExecutableIndex.reset(); + for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + { + if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature)) + { + mCachedVertexExecutableIndex = executableIndex; + break; + } + } +} + +void ProgramD3D::updateCachedPixelExecutableIndex() +{ + mCachedPixelExecutableIndex.reset(); + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache)) + { + mCachedPixelExecutableIndex = executableIndex; + break; + } + } } + +void ProgramD3D::linkResources(const gl::Context *context, + const gl::ProgramLinkedResources &resources) +{ + UniformBlockInfo uniformBlockInfo; + + if (mState.getAttachedVertexShader()) + { + uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedVertexShader()); + } + + if (mState.getAttachedFragmentShader()) + { + uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedFragmentShader()); + } + + if (mState.getAttachedComputeShader()) + { + uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedComputeShader()); + } + + // Gather interface block info. + auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name, + const std::string &mappedName, size_t *sizeOut) { + return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut); + }; + + auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name, + const std::string &mappedName, + sh::BlockMemberInfo *infoOut) { + return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut); + }; + + resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo); + initializeUniformBlocks(); + + // TODO(jiajia.qin@intel.com): Determine correct shader storage block info. + auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName, + size_t *sizeOut) { + *sizeOut = 0; + return true; + }; + + auto getShaderStorageBlockMemberInfo = + [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) { + *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return true; + }; + + resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize, + getShaderStorageBlockMemberInfo); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h index 3dfe52db1c..829757a73e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -17,7 +17,7 @@ #include "libANGLE/formatutils.h" #include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h" -#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" +#include "platform/WorkaroundsD3D.h" namespace rx { @@ -32,52 +32,71 @@ class ShaderExecutableD3D; #endif // Helper struct representing a single shader uniform -struct D3DUniform : angle::NonCopyable +// TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate +// register indices. +struct D3DUniform : private angle::NonCopyable { - D3DUniform(GLenum typeIn, + D3DUniform(GLenum type, const std::string &nameIn, - unsigned int arraySizeIn, + const std::vector<unsigned int> &arraySizesIn, bool defaultBlock); ~D3DUniform(); bool isSampler() const; - unsigned int elementCount() const { return std::max(1u, arraySize); } + + bool isArray() const { return !arraySizes.empty(); } + unsigned int getArraySizeProduct() const; + bool isReferencedByVertexShader() const; bool isReferencedByFragmentShader() const; + bool isReferencedByComputeShader() const; - // Duplicated from the GL layer - GLenum type; - std::string name; - unsigned int arraySize; + const uint8_t *firstNonNullData() const; + const uint8_t *getDataPtrToElement(size_t elementIndex) const; - // Pointer to a system copy of the data. - // TODO(jmadill): remove this in favor of gl::LinkedUniform::data(). - uint8_t *data; + // Duplicated from the GL layer + const gl::UniformTypeInfo &typeInfo; + std::string name; // Names of arrays don't include [0], unlike at the GL layer. + std::vector<unsigned int> arraySizes; - // Has the data been updated since the last sync? - bool dirty; + // Pointer to a system copies of the data. Separate pointers for each uniform storage type. + uint8_t *vsData; + uint8_t *psData; + uint8_t *csData; // Register information. unsigned int vsRegisterIndex; unsigned int psRegisterIndex; + unsigned int csRegisterIndex; 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; + + // Special buffer for sampler values. + std::vector<GLint> mSamplerData; }; struct D3DUniformBlock { - D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {} + D3DUniformBlock() + : vsRegisterIndex(GL_INVALID_INDEX), + psRegisterIndex(GL_INVALID_INDEX), + csRegisterIndex(GL_INVALID_INDEX) + { + } bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } + bool computeStaticUse() const { return csRegisterIndex != GL_INVALID_INDEX; } + unsigned int vsRegisterIndex; unsigned int psRegisterIndex; + unsigned int csRegisterIndex; }; struct D3DVarying final @@ -97,24 +116,24 @@ struct D3DVarying final unsigned int outputSlot; }; -class ProgramD3DMetadata : angle::NonCopyable +class ProgramD3DMetadata final : angle::NonCopyable { public: - ProgramD3DMetadata(int rendererMajorShaderModel, - const std::string &shaderModelSuffix, - bool usesInstancedPointSpriteEmulation, - bool usesViewScale, + ProgramD3DMetadata(RendererD3D *renderer, const ShaderD3D *vertexShader, const ShaderD3D *fragmentShader); int getRendererMajorShaderModel() const; - bool usesBroadcast(const gl::Data &data) const; - bool usesFragDepth(const gl::Program::Data &programData) 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 hasANGLEMultiviewEnabled() const; + bool usesViewID() const; + bool canSelectViewInVertexShader() const; bool addsPointCoordToVertexShader() const; bool usesTransformFeedbackGLPosition() const; bool usesSystemValuePointSize() const; @@ -127,6 +146,9 @@ class ProgramD3DMetadata : angle::NonCopyable const std::string mShaderModelSuffix; const bool mUsesInstancedPointSpriteEmulation; const bool mUsesViewScale; + const bool mHasANGLEMultiviewEnabled; + const bool mUsesViewID; + const bool mCanSelectViewInVertexShader; const ShaderD3D *mVertexShader; const ShaderD3D *mFragmentShader; }; @@ -134,10 +156,8 @@ class ProgramD3DMetadata : angle::NonCopyable class ProgramD3D : public ProgramImpl { public: - typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; - - ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer); - virtual ~ProgramD3D(); + ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer); + ~ProgramD3D() override; const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } @@ -145,116 +165,157 @@ class ProgramD3D : public ProgramImpl unsigned int samplerIndex, const gl::Caps &caps) const; GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; - GLint getUsedSamplerRange(gl::SamplerType type) const; - void updateSamplerMapping(); + GLuint getUsedSamplerRange(gl::SamplerType type) const; + + enum SamplerMapping + { + WasDirty, + WasClean, + }; + + SamplerMapping updateSamplerMapping(); bool usesPointSize() const { return mUsesPointSize; } bool usesPointSpriteEmulation() const; bool usesGeometryShader(GLenum drawMode) const; + bool usesGeometryShaderForPointSpriteEmulation() const; bool usesInstancedPointSpriteEmulation() const; - LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; - gl::Error save(gl::BinaryOutputStream *stream) override; + gl::LinkResult load(const gl::Context *context, + gl::InfoLog &infoLog, + gl::BinaryInputStream *stream) override; + void save(const gl::Context *context, gl::BinaryOutputStream *stream) override; void setBinaryRetrievableHint(bool retrievable) override; + void setSeparable(bool separable) 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::Data &data, + gl::Error getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getGeometryExecutableForPrimitiveType(const gl::Context *context, GLenum drawMode, ShaderExecutableD3D **outExecutable, gl::InfoLog *infoLog); - - LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; + gl::Error getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getComputeExecutable(ShaderExecutableD3D **outExecutable); + gl::LinkResult link(const gl::Context *context, + const gl::ProgramLinkedResources &resources, + 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::Data &data); + void updateUniformBufferCache(const gl::Caps &caps, + unsigned int reservedVertex, + unsigned int reservedFragment); + const std::vector<GLint> &getVertexUniformBufferCache() const; + const std::vector<GLint> &getFragmentUniformBufferCache() const; + 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 setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, - const GLfloat *value); + const GLfloat *value) override; + + void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; + void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; + void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; - const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } - const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage.get(); } + UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage.get(); } + UniformStorageD3D &getComputeUniformStorage() const { return *mComputeUniformStorage.get(); } unsigned int getSerial() const; - void sortAttributesByLayout( - const std::vector<TranslatedAttribute> &unsortedAttributes, - int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], - const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const; - const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndexes; } - const SemanticIndexArray &getAttributesByLayout() const { return mAttributesByLayout; } + const AttribIndexArray &getAttribLocationToD3DSemantics() const + { + return mAttribLocationToD3DSemantic; + } - void updateCachedInputLayout(const gl::State &state); - const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; } + void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); + void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); bool isSamplerMappingDirty() { return mDirtySamplerMapping; } + // Checks if we need to recompile certain shaders. + bool hasVertexExecutableForCachedInputLayout(); + bool hasGeometryExecutableForPrimitiveType(GLenum drawMode); + bool hasPixelExecutableForCachedOutputLayout(); + + bool areVertexUniformsDirty() const { return mVertexUniformsDirty; } + bool areFragmentUniformsDirty() const { return mFragmentUniformsDirty; } + bool areComputeUniformsDirty() const { return mComputeUniformsDirty; } + const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; } + void markUniformsClean(); + private: + // These forward-declared tasks are used for multi-thread shader compiles. + class GetExecutableTask; + class GetVertexExecutableTask; + class GetPixelExecutableTask; + class GetGeometryExecutableTask; + class VertexExecutable { public: - typedef std::vector<bool> Signature; + enum HLSLAttribType + { + FLOAT, + UNSIGNED_INT, + SIGNED_INT, + }; + + typedef std::vector<HLSLAttribType> Signature; VertexExecutable(const gl::InputLayout &inputLayout, const Signature &signature, @@ -271,6 +332,8 @@ class ProgramD3D : public ProgramImpl ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: + static HLSLAttribType GetAttribType(GLenum type); + gl::InputLayout mInputs; Signature mSignature; ShaderExecutableD3D *mShaderExecutable; @@ -307,62 +370,105 @@ class ProgramD3D : public ProgramImpl typedef std::map<std::string, D3DUniform *> D3DUniformMap; - void defineUniformsAndAssignRegisters(); + void defineUniformsAndAssignRegisters(const gl::Context *context); void defineUniformBase(const gl::Shader *shader, const sh::Uniform &uniform, D3DUniformMap *uniformMap); + void defineStructUniformFields(GLenum shaderType, + const std::vector<sh::ShaderVariable> &fields, + const std::string &namePrefix, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap); + void defineArrayOfStructsUniformFields(GLenum shaderType, + const sh::ShaderVariable &uniform, + unsigned int arrayNestingIndex, + const std::string &prefix, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap); + void defineArrayUniformElements(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap); void defineUniform(GLenum shaderType, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder, D3DUniformMap *uniformMap); void assignAllSamplerRegisters(); - void assignSamplerRegisters(const D3DUniform *d3dUniform); + void assignSamplerRegisters(size_t uniformIndex); static void AssignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, + const gl::UniformTypeInfo &typeInfo, unsigned int samplerCount, std::vector<Sampler> &outSamplers, GLuint *outUsedRange); + template <typename DestT> + void getUniformInternal(GLint location, DestT *dataOut) const; + + template <typename T> + void setUniformImpl(const gl::VariableLocation &locationInfo, + GLsizei count, + const T *v, + uint8_t *targetData, + GLenum uniformType); + template <typename T> - void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType); + void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType); template <int cols, int rows> - void setUniformMatrixfv(GLint location, - GLsizei count, - GLboolean transpose, - const GLfloat *value, - GLenum targetUniformType); + bool setUniformMatrixfvImpl(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + uint8_t *targetData, + GLenum targetUniformType); - LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog); + template <int cols, int rows> + void setUniformMatrixfvInternal(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType); - void gatherTransformFeedbackVaryings(const VaryingPacking &varyings); + gl::LinkResult compileProgramExecutables(const gl::Context *context, gl::InfoLog &infoLog); + gl::LinkResult compileComputeExecutable(const gl::Context *context, gl::InfoLog &infoLog); + + void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, + const BuiltinInfo &builtins); D3DUniform *getD3DUniformByName(const std::string &name); D3DUniform *getD3DUniformFromLocation(GLint location); + const D3DUniform *getD3DUniformFromLocation(GLint location) const; - void initSemanticIndex(); - void initAttributesByLayout(); + void initAttribLocationsToD3DSemantic(const gl::Context *context); void reset(); - void assignUniformBlockRegisters(); + void initializeUniformBlocks(); + + void updateCachedInputLayoutFromShader(const gl::Context *context); + void updateCachedOutputLayoutFromShader(); + void updateCachedVertexExecutableIndex(); + void updateCachedPixelExecutableIndex(); - void initUniformBlockInfo(); - size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock); + void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources); RendererD3D *mRenderer; DynamicHLSL *mDynamicHLSL; - std::vector<VertexExecutable *> mVertexExecutables; - std::vector<PixelExecutable *> mPixelExecutables; - std::vector<ShaderExecutableD3D *> mGeometryExecutables; + std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables; + std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; + std::vector<std::unique_ptr<ShaderExecutableD3D>> mGeometryExecutables; + std::unique_ptr<ShaderExecutableD3D> mComputeExecutable; std::string mVertexHLSL; - D3DCompilerWorkarounds mVertexWorkarounds; + angle::CompilerWorkaroundsD3D mVertexWorkarounds; std::string mPixelHLSL; - D3DCompilerWorkarounds mPixelWorkarounds; + angle::CompilerWorkaroundsD3D mPixelWorkarounds; bool mUsesFragDepth; + bool mHasANGLEMultiviewEnabled; + bool mUsesViewID; std::vector<PixelShaderOutputVariable> mPixelShaderKey; // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output @@ -373,20 +479,23 @@ class ProgramD3D : public ProgramImpl bool mUsesPointSize; bool mUsesFlatInterpolation; - UniformStorageD3D *mVertexUniformStorage; - UniformStorageD3D *mFragmentUniformStorage; + std::unique_ptr<UniformStorageD3D> mVertexUniformStorage; + std::unique_ptr<UniformStorageD3D> mFragmentUniformStorage; + std::unique_ptr<UniformStorageD3D> mComputeUniformStorage; std::vector<Sampler> mSamplersPS; std::vector<Sampler> mSamplersVS; + std::vector<Sampler> mSamplersCS; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; + GLuint mUsedComputeSamplerRange; bool mDirtySamplerMapping; - // Cache for getPixelExecutableForFramebuffer - std::vector<GLenum> mPixelShaderOutputFormatCache; + // Cache for pixel shader output layout to save reallocations. + std::vector<GLenum> mPixelShaderOutputLayoutCache; + Optional<size_t> mCachedPixelExecutableIndex; - SemanticIndexArray mSemanticIndexes; - SemanticIndexArray mAttributesByLayout; + AttribIndexArray mAttribLocationToD3DSemantic; unsigned int mSerial; @@ -394,17 +503,21 @@ class ProgramD3D : public ProgramImpl std::vector<GLint> mFragmentUBOCache; VertexExecutable::Signature mCachedVertexSignature; gl::InputLayout mCachedInputLayout; + Optional<size_t> mCachedVertexExecutableIndex; 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; + bool mVertexUniformsDirty; + bool mFragmentUniformsDirty; + bool mComputeUniformsDirty; static unsigned int issueSerial(); static unsigned int mCurrentSerial; + + Serial mCurrentVertexArrayStateSerial; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h index b2d895d9c6..fde96133b0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h @@ -21,7 +21,7 @@ class RenderTargetD3D : public FramebufferAttachmentRenderTarget { public: RenderTargetD3D(); - virtual ~RenderTargetD3D(); + ~RenderTargetD3D() override; virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; @@ -29,10 +29,14 @@ class RenderTargetD3D : public FramebufferAttachmentRenderTarget virtual GLenum getInternalFormat() const = 0; virtual GLsizei getSamples() const = 0; gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } + bool isMultisampled() const { return getSamples() > 0; } virtual unsigned int getSerial() const; static unsigned int issueSerials(unsigned int count); + // Only currently applies to D3D11. + virtual void signalDirty(const gl::Context *context) {} + private: const unsigned int mSerial; static unsigned int mCurrentSerial; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp index 991801a091..d799e0b992 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -27,12 +27,25 @@ RenderbufferD3D::~RenderbufferD3D() mImage = nullptr; } -gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height) +gl::Error RenderbufferD3D::onDestroy(const gl::Context *context) { - return setStorageMultisample(0, internalformat, width, height); + deleteRenderTarget(context); + return gl::NoError(); } -gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) +gl::Error RenderbufferD3D::setStorage(const gl::Context *context, + GLenum internalformat, + size_t width, + size_t height) +{ + return setStorageMultisample(context, 0, internalformat, width, height); +} + +gl::Error RenderbufferD3D::setStorageMultisample(const gl::Context *context, + 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 @@ -48,54 +61,70 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal // 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->getRendererTextureCaps().get(creationFormat); + 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()); + return gl::OutOfMemory() << "Renderbuffer format does not support " << samples + << " samples, " << formatCaps.getMaxSamples() + << " is the maximum."; } - RenderTargetD3D *newRT = NULL; - gl::Error error = - mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height), - creationFormat, static_cast<GLsizei>(samples), &newRT); - if (error.isError()) - { - return error; - } + RenderTargetD3D *newRT = nullptr; + ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height), + creationFormat, static_cast<GLsizei>(samples), &newRT)); - SafeDelete(mRenderTarget); + deleteRenderTarget(context); mImage = nullptr; mRenderTarget = newRT; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image) +gl::Error RenderbufferD3D::setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) { mImage = GetImplAs<EGLImageD3D>(image); - SafeDelete(mRenderTarget); + deleteRenderTarget(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget) +gl::Error RenderbufferD3D::getRenderTarget(const gl::Context *context, + RenderTargetD3D **outRenderTarget) { if (mImage) { - return mImage->getRenderTarget(outRenderTarget); + return mImage->getRenderTarget(context, outRenderTarget); } else { *outRenderTarget = mRenderTarget; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } -gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, +gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context, + GLenum /*binding*/, + const gl::ImageIndex & /*imageIndex*/, FramebufferAttachmentRenderTarget **rtOut) { - return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut)); + return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut)); } +void RenderbufferD3D::deleteRenderTarget(const gl::Context *context) +{ + if (mRenderTarget) + { + mRenderTarget->signalDirty(context); + SafeDelete(mRenderTarget); + } } + +gl::Error RenderbufferD3D::initializeContents(const gl::Context *context, + const gl::ImageIndex &imageIndex) +{ + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(getRenderTarget(context, &renderTarget)); + return mRenderer->initRenderTarget(renderTarget); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h index 20f6a10b2d..b50eff7db7 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h @@ -25,20 +25,33 @@ class RenderbufferD3D : public RenderbufferImpl { public: RenderbufferD3D(RendererD3D *renderer); - virtual ~RenderbufferD3D(); + ~RenderbufferD3D() override; - gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; - gl::Error setStorageMultisample(size_t samples, + gl::Error onDestroy(const gl::Context *context) override; + + gl::Error setStorage(const gl::Context *context, + GLenum internalformat, + size_t width, + size_t height) override; + gl::Error setStorageMultisample(const gl::Context *context, + size_t samples, GLenum internalformat, size_t width, size_t height) override; - gl::Error setStorageEGLImageTarget(egl::Image *image) override; + gl::Error setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) override; - gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget); - gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRenderTarget); + gl::Error getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) override; + gl::Error initializeContents(const gl::Context *context, + const gl::ImageIndex &imageIndex) override; + private: + void deleteRenderTarget(const gl::Context *context); + RendererD3D *mRenderer; RenderTargetD3D *mRenderTarget; EGLImageD3D *mImage; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp index 105587f62c..2167200a91 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -8,43 +8,39 @@ #include "libANGLE/renderer/d3d/RendererD3D.h" -#include "common/debug.h" #include "common/MemoryBuffer.h" +#include "common/debug.h" #include "common/utilities.h" +#include "libANGLE/Context.h" #include "libANGLE/Display.h" -#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ContextImpl.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" +#include "libANGLE/renderer/d3d/TextureD3D.h" namespace rx { -namespace -{ -// 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 - RendererD3D::RendererD3D(egl::Display *display) : mDisplay(display), - mDeviceLost(false), - mAnnotator(nullptr), mPresentPathFastEnabled(false), - mScratchMemoryBufferResetCounter(0), + mCapsInitialized(false), mWorkaroundsInitialized(false), - mDisjoint(false) + mDisjoint(false), + mDeviceLost(false), + mWorkerThreadPool(4) { } @@ -55,451 +51,29 @@ RendererD3D::~RendererD3D() void RendererD3D::cleanup() { - mScratchMemoryBuffer.resize(0); - for (auto &incompleteTexture : mIncompleteTextures) - { - incompleteTexture.second.set(NULL); - } - mIncompleteTextures.clear(); - - if (mAnnotator != nullptr) - { - gl::UninitializeDebugAnnotations(); - SafeDelete(mAnnotator); - } -} - -SamplerImpl *RendererD3D::createSampler() -{ - return new SamplerD3D(); -} - -gl::Error RendererD3D::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) -{ - return genericDrawArrays(data, mode, first, count, 0); -} - -gl::Error RendererD3D::drawArraysInstanced(const gl::Data &data, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instanceCount) -{ - return genericDrawArrays(data, mode, first, count, instanceCount); -} - -gl::Error RendererD3D::drawElements(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - const gl::IndexRange &indexRange) -{ - return genericDrawElements(data, mode, count, type, indices, 0, indexRange); -} - -gl::Error RendererD3D::drawElementsInstanced(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances, - const gl::IndexRange &indexRange) -{ - return genericDrawElements(data, mode, count, type, indices, instances, indexRange); -} - -gl::Error RendererD3D::drawRangeElements(const gl::Data &data, - GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const GLvoid *indices, - const gl::IndexRange &indexRange) -{ - return genericDrawElements(data, mode, count, type, indices, 0, indexRange); -} - -gl::Error RendererD3D::genericDrawElements(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances, - const gl::IndexRange &indexRange) -{ - gl::Program *program = data.state->getProgram(); - ASSERT(program != nullptr); - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - bool usesPointSize = programD3D->usesPointSize(); - - programD3D->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count, usesPointSize)) - { - return gl::Error(GL_NO_ERROR); - } - - error = updateState(data, mode); - if (error.isError()) - { - return error; - } - - TranslatedIndexData indexInfo; - indexInfo.indexRange = indexRange; - - error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo); - if (error.isError()) - { - return error; - } - - applyTransformFeedbackBuffers(*data.state); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation - // layer. - ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); - - size_t vertexCount = indexInfo.indexRange.vertexCount(); - error = applyVertexBuffer(*data.state, mode, static_cast<GLsizei>(indexInfo.indexRange.start), - static_cast<GLsizei>(vertexCount), instances, &indexInfo); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyShaders(data, mode); - if (error.isError()) - { - return error; - } - - error = programD3D->applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::genericDrawArrays(const gl::Data &data, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances) -{ - gl::Program *program = data.state->getProgram(); - ASSERT(program != nullptr); - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - bool usesPointSize = programD3D->usesPointSize(); - - programD3D->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count, usesPointSize)) - { - return gl::Error(GL_NO_ERROR); - } - - error = updateState(data, mode); - if (error.isError()) - { - return error; - } - - applyTransformFeedbackBuffers(*data.state); - - error = applyVertexBuffer(*data.state, mode, first, count, instances, nullptr); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyShaders(data, mode); - if (error.isError()) - { - return error; - } - - error = programD3D->applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawArraysImpl(data, mode, count, instances); - if (error.isError()) - { - return error; - } - - if (data.state->isTransformFeedbackActiveUnpaused()) - { - markTransformFeedbackUsage(data); - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) -{ - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - - unsigned int samplerRange = static_cast<unsigned int>(programD3D->getUsedSamplerRange(type)); - - for (unsigned int i = 0; i < samplerRange; i++) - { - GLenum textureType = programD3D->getSamplerTextureType(type, i); - GLint textureUnit = programD3D->getSamplerMapping(type, i, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - if (texture->getTextureState().swizzleRequired()) - { - gl::Error error = generateSwizzle(texture); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data) -{ - gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); - if (error.isError()) - { - return error; - } - - error = generateSwizzles(data, gl::SAMPLER_PIXEL); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples) -{ - unsigned int mask = 0; - if (data.state->isSampleCoverageEnabled()) - { - GLclampf coverageValue = data.state->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 = data.state->getSampleCoverageInvert(); - if (coverageInvert) - { - mask = ~mask; - } - } - else - { - mask = 0xFFFFFFFF; - } - - return mask; -} - -// Applies the shaders and shader constants to the Direct3D device -gl::Error RendererD3D::applyShaders(const gl::Data &data, GLenum drawMode) -{ - gl::Program *program = data.state->getProgram(); - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - programD3D->updateCachedInputLayout(*data.state); - - gl::Error error = applyShadersImpl(data, drawMode); - if (error.isError()) - { - return error; - } - - return programD3D->applyUniforms(drawMode); -} - -// 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(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount) -{ - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->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, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - - gl::Sampler *samplerObject = data.state->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->isSamplerComplete(samplerState, data) && - !std::binary_search(framebufferTextures.begin(), - framebufferTextures.begin() + framebufferTextureCount, texture)) - { - gl::Error error = setSamplerState(shaderType, samplerIndex, texture, samplerState); - if (error.isError()) - { - return error; - } - - error = setTexture(shaderType, samplerIndex, texture); - if (error.isError()) - { - return error; - } - } - else - { - // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. - gl::Texture *incompleteTexture = getIncompleteTexture(textureType); - - gl::Error error = setSamplerState(shaderType, samplerIndex, incompleteTexture, - incompleteTexture->getSamplerState()); - if (error.isError()) - { - return error; - } - - error = setTexture(shaderType, samplerIndex, incompleteTexture); - if (error.isError()) - { - return error; - } - } - } - else - { - // No texture bound to this slot even though it is used by the shader, bind a NULL texture - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits - : data.caps->maxVertexTextureImageUnits; - clearTextures(shaderType, samplerRange, samplerCount); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::applyTextures(const gl::Data &data) -{ - FramebufferTextureArray framebufferTextures; - size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures); - - gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferTextures, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferTextures, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); + mIncompleteTextures.onDestroy(mDisplay->getProxyContext()); } -bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) +bool RendererD3D::skipDraw(const gl::State &glState, GLenum drawMode) { - const gl::State &state = *data.state; - if (drawMode == GL_POINTS) { - bool usesPointSize = GetImplAs<ProgramD3D>(state.getProgram())->usesPointSize(); + bool usesPointSize = GetImplAs<ProgramD3D>(glState.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()) + if (!usesPointSize && !glState.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."); - + // Notify developers of risking undefined behavior. + WARN() << "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) + if (glState.getRasterizerState().cullFace && + glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack) { return true; } @@ -508,196 +82,179 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) return false; } -void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) +gl::Error RendererD3D::getIncompleteTexture(const gl::Context *context, + GLenum type, + gl::Texture **textureOut) { - const gl::TransformFeedback *transformFeedback = data.state->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()); - bufferD3D->markTransformFeedbackUsage(); - } - } + return mIncompleteTextures.getIncompleteTexture(context, type, this, textureOut); } -size_t RendererD3D::getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray) +GLenum RendererD3D::getResetStatus() { - size_t textureCount = 0; - - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++) + if (!mDeviceLost) { - const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); - if (attachment && attachment->type() == GL_TEXTURE) + if (testDeviceLost()) { - (*outTextureArray)[textureCount++] = attachment->getTexture(); + mDeviceLost = true; + notifyDeviceLost(); + return GL_UNKNOWN_CONTEXT_RESET_EXT; } + return GL_NO_ERROR; } - const gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE) + if (testDeviceResettable()) { - (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture(); + return GL_NO_ERROR; } - std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount); - - return textureCount; -} - -gl::Texture *RendererD3D::getIncompleteTexture(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); - - // Skip the API layer to avoid needing to pass the Context and mess with dirty bits. - gl::Texture *t = - new gl::Texture(createTexture(type), std::numeric_limits<GLuint>::max(), type); - t->setStorage(type, 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(type, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, unpack, - color); - } - - mIncompleteTextures[type].set(t); - } - - return mIncompleteTextures[type].get(); -} - -bool RendererD3D::isDeviceLost() const -{ - return mDeviceLost; + return GL_UNKNOWN_CONTEXT_RESET_EXT; } void RendererD3D::notifyDeviceLost() { - mDeviceLost = true; mDisplay->notifyDeviceLost(); } std::string RendererD3D::getVendorString() const { - LUID adapterLuid = { 0 }; + LUID adapterLuid = {0}; if (getLUID(&adapterLuid)) { char adapterLuidString[64]; - sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", + adapterLuid.HighPart, adapterLuid.LowPart); return std::string(adapterLuidString); } return std::string(""); } -gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut) +void RendererD3D::setGPUDisjoint() { - if (mScratchMemoryBuffer.size() == requestedSize) - { - mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; - *bufferOut = &mScratchMemoryBuffer; - return gl::Error(GL_NO_ERROR); - } - - if (mScratchMemoryBuffer.size() > requestedSize) - { - mScratchMemoryBufferResetCounter--; - } + mDisjoint = true; +} - 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; - } +GLint RendererD3D::getGPUDisjoint() +{ + bool disjoint = mDisjoint; - ASSERT(mScratchMemoryBuffer.size() >= requestedSize); + // Disjoint flag is cleared when read + mDisjoint = false; - *bufferOut = &mScratchMemoryBuffer; - return gl::Error(GL_NO_ERROR); + return disjoint; } -void RendererD3D::insertEventMarker(GLsizei length, const char *marker) +GLint64 RendererD3D::getTimestamp() { - std::vector<wchar_t> wcstring (length + 1); - size_t convertedChars = 0; - errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE); - if (err == 0) - { - getAnnotator()->setMarker(wcstring.data()); - } + // D3D has no way to get an actual timestamp reliably so 0 is returned + return 0; } -void RendererD3D::pushGroupMarker(GLsizei length, const char *marker) +void RendererD3D::ensureCapsInitialized() const { - std::vector<wchar_t> wcstring(length + 1); - size_t convertedChars = 0; - errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE); - if (err == 0) + if (!mCapsInitialized) { - getAnnotator()->beginEvent(wcstring.data()); + generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations); + mCapsInitialized = true; } } -void RendererD3D::popGroupMarker() +const gl::Caps &RendererD3D::getNativeCaps() const { - getAnnotator()->endEvent(); + ensureCapsInitialized(); + return mNativeCaps; } -void RendererD3D::setGPUDisjoint() +const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const { - mDisjoint = true; + ensureCapsInitialized(); + return mNativeTextureCaps; } -GLint RendererD3D::getGPUDisjoint() +const gl::Extensions &RendererD3D::getNativeExtensions() const { - bool disjoint = mDisjoint; + ensureCapsInitialized(); + return mNativeExtensions; +} - // Disjoint flag is cleared when read - mDisjoint = false; +const gl::Limitations &RendererD3D::getNativeLimitations() const +{ + ensureCapsInitialized(); + return mNativeLimitations; +} - return disjoint; +angle::WorkerThreadPool *RendererD3D::getWorkerThreadPool() +{ + return &mWorkerThreadPool; } -GLint64 RendererD3D::getTimestamp() +Serial RendererD3D::generateSerial() { - // D3D has no way to get an actual timestamp reliably so 0 is returned - return 0; + return mSerialFactory.generate(); } -void RendererD3D::onMakeCurrent(const gl::Data &data) +bool InstancedPointSpritesActive(ProgramD3D *programD3D, GLenum mode) { + return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() && + mode == GL_POINTS; } -void RendererD3D::initializeDebugAnnotator() +gl::Error RendererD3D::initRenderTarget(RenderTargetD3D *renderTarget) { - createAnnotator(); - ASSERT(mAnnotator); - gl::InitializeDebugAnnotations(mAnnotator); + return clearRenderTarget(renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0); } -gl::DebugAnnotator *RendererD3D::getAnnotator() +gl::Error RendererD3D::initializeMultisampleTextureToBlack(const gl::Context *context, + gl::Texture *glTexture) { - ASSERT(mAnnotator); - return mAnnotator; + ASSERT(glTexture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(glTexture); + gl::ImageIndex index = gl::ImageIndex::Make2DMultisample(); + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(textureD3D->getRenderTarget(context, index, &renderTarget)); + return clearRenderTarget(renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0); } + +unsigned int GetBlendSampleMask(const gl::State &glState, int samples) +{ + unsigned int mask = 0; + if (glState.isSampleCoverageEnabled()) + { + GLfloat 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; + } + + if (glState.isSampleMaskEnabled()) + { + mask &= glState.getSampleMaskWord(0); + } + + return mask; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h index f956f037e2..dcc98f2ec6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -9,19 +9,21 @@ #ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ #define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ -#include "common/debug.h" +#include <array> + +#include "common/Color.h" #include "common/MemoryBuffer.h" -#include "libANGLE/Data.h" +#include "common/debug.h" +#include "libANGLE/ContextState.h" #include "libANGLE/Device.h" +#include "libANGLE/Version.h" +#include "libANGLE/WorkerThread.h" +#include "libANGLE/angletypes.h" #include "libANGLE/formatutils.h" -#include "libANGLE/renderer/Renderer.h" #include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/formatutilsD3D.h" -#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" - -//FIXME(jmadill): std::array is currently prohibited by Chromium style guide -#include <array> +#include "libANGLE/renderer/renderer_utils.h" +#include "platform/WorkaroundsD3D.h" namespace egl { @@ -30,7 +32,7 @@ class ConfigSet; namespace gl { -class DebugAnnotator; +class FramebufferState; class InfoLog; class Texture; struct LinkedVarying; @@ -38,28 +40,24 @@ 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; @@ -76,7 +74,7 @@ enum RendererClass }; // Useful for unit testing -class BufferFactoryD3D +class BufferFactoryD3D : angle::NonCopyable { public: BufferFactoryD3D() {} @@ -88,52 +86,32 @@ class BufferFactoryD3D // TODO(jmadill): add VertexFormatCaps virtual VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const = 0; virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0; + + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. + virtual gl::ErrorOrResult<unsigned int> getVertexSpaceRequired( + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const = 0; }; -class RendererD3D : public Renderer, public BufferFactoryD3D +using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>; + +class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitializer { public: explicit RendererD3D(egl::Display *display); - virtual ~RendererD3D(); + ~RendererD3D() override; virtual egl::Error initialize() = 0; - virtual egl::ConfigSet generateConfigs() const = 0; + virtual egl::ConfigSet generateConfigs() = 0; virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0; - gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) override; - gl::Error drawArraysInstanced(const gl::Data &data, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instanceCount) override; - - gl::Error drawElements(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - const gl::IndexRange &indexRange) override; - gl::Error drawElementsInstanced(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances, - const gl::IndexRange &indexRange) override; - gl::Error drawRangeElements(const gl::Data &data, - GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const GLvoid *indices, - const gl::IndexRange &indexRange) override; - - bool isDeviceLost() const override; - std::string getVendorString() const override; - - SamplerImpl *createSampler() override; + virtual ContextImpl *createContext(const gl::ContextState &state) = 0; + + std::string getVendorString() const; virtual int getMinorShaderModel() const = 0; virtual std::string getShaderModelSuffix() const = 0; @@ -141,204 +119,241 @@ class RendererD3D : public Renderer, public BufferFactoryD3D // Direct3D Specific methods virtual DeviceIdentifier getAdapterIdentifier() const = 0; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + 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 gl::Error generateSwizzle(gl::Texture *texture) = 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::Data &data, - const std::vector<GLint> &vertexUniformBuffers, - const std::vector<GLint> &fragmentUniformBuffers) = 0; - - virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0; - - virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyUniforms(const ProgramD3D &programD3D, - GLenum drawMode, - const std::vector<D3DUniform *> &uniformArray) = 0; - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0; - virtual gl::Error applyVertexBuffer(const gl::State &state, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances, - TranslatedIndexData *indexInfo) = 0; - virtual gl::Error applyIndexBuffer(const gl::Data &data, - const GLvoid *indices, - GLsizei count, - GLenum mode, - GLenum type, - TranslatedIndexData *indexInfo) = 0; - virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; - - virtual unsigned int getReservedVertexUniformVectors() const = 0; - virtual unsigned int getReservedFragmentUniformVectors() const = 0; - virtual unsigned int getReservedVertexUniformBuffers() const = 0; - virtual unsigned int getReservedFragmentUniformBuffers() const = 0; + EGLint orientation, + EGLint samples) = 0; + virtual egl::Error getD3DTextureInfo(const egl::Config *configuration, + 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 int getMajorShaderModel() const = 0; - const WorkaroundsD3D &getWorkarounds() const; + const angle::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 copyImage2D(const gl::Context *context, + 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::Context *context, + 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::Context *context, + 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::Context *context, + 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::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) = 0; + virtual gl::Error copyCompressedTexture(const gl::Context *context, + 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, + virtual gl::Error loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - ShaderExecutableD3D **outExecutable) = 0; + ShaderExecutableD3D **outExecutable) = 0; virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) = 0; + virtual gl::Error ensureHLSLCompilerInitialized() = 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 generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) = 0; + virtual gl::Error generateMipmap(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source) = 0; + virtual gl::Error generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) = 0; + virtual gl::Error copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) = 0; virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; - virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) = 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; + virtual TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) = 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; + virtual gl::Error fastCopyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) = 0; // Device lost - void notifyDeviceLost() override; + 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; - gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); - - // EXT_debug_marker - void insertEventMarker(GLsizei length, const char *marker) override; - void pushGroupMarker(GLsizei length, const char *marker) override; - void popGroupMarker() override; - void setGPUDisjoint(); - GLint getGPUDisjoint() override; - GLint64 getTimestamp() override; - - void onMakeCurrent(const gl::Data &data) override; + 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 gl::Error clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) = 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; + + gl::Error initRenderTarget(RenderTargetD3D *renderTarget); + + angle::WorkerThreadPool *getWorkerThreadPool(); + + gl::Error getIncompleteTexture(const gl::Context *context, + GLenum type, + gl::Texture **textureOut); + + Serial generateSerial(); + + virtual bool canSelectViewInVertexShader() const = 0; + + gl::Error initializeMultisampleTextureToBlack(const gl::Context *context, + gl::Texture *glTexture) override; + protected: virtual bool getLUID(LUID *adapterLuid) const = 0; - virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0; + virtual void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const = 0; void cleanup(); - virtual void createAnnotator() = 0; - - static unsigned int GetBlendSampleMask(const gl::Data &data, int samples); - // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. + bool skipDraw(const gl::State &glState, GLenum drawMode); egl::Display *mDisplay; - bool mDeviceLost; - - void initializeDebugAnnotator(); - gl::DebugAnnotator *mAnnotator; - - std::vector<TranslatedAttribute> mTranslatedAttribCache; bool mPresentPathFastEnabled; private: - gl::Error genericDrawArrays(const gl::Data &data, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances); - - gl::Error genericDrawElements(const gl::Data &data, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances, - const gl::IndexRange &indexRange); - - virtual gl::Error drawArraysImpl(const gl::Data &data, - GLenum mode, - GLsizei count, - GLsizei instances) = 0; - virtual gl::Error drawElementsImpl(const gl::Data &data, - const TranslatedIndexData &indexInfo, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances) = 0; - - //FIXME(jmadill): std::array is currently prohibited by Chromium style guide - typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray; - - gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); - gl::Error generateSwizzles(const gl::Data &data); - - gl::Error applyState(const gl::Data &data, GLenum drawMode); - gl::Error applyShaders(const gl::Data &data, GLenum drawMode); - gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount); - gl::Error applyTextures(const gl::Data &data); - - bool skipDraw(const gl::Data &data, GLenum drawMode); - void markTransformFeedbackUsage(const gl::Data &data); - - size_t getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray); - gl::Texture *getIncompleteTexture(GLenum type); - - gl::DebugAnnotator *getAnnotator(); - - virtual WorkaroundsD3D generateWorkarounds() const = 0; - - gl::TextureMap mIncompleteTextures; - MemoryBuffer mScratchMemoryBuffer; - unsigned int mScratchMemoryBufferResetCounter; + void ensureCapsInitialized() const; + + virtual angle::WorkaroundsD3D generateWorkarounds() const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mNativeCaps; + mutable gl::TextureCapsMap mNativeTextureCaps; + mutable gl::Extensions mNativeExtensions; + mutable gl::Limitations mNativeLimitations; + + IncompleteTextureSet mIncompleteTextures; mutable bool mWorkaroundsInitialized; - mutable WorkaroundsD3D mWorkarounds; + mutable angle::WorkaroundsD3D mWorkarounds; bool mDisjoint; + bool mDeviceLost; + + angle::WorkerThreadPool mWorkerThreadPool; + + SerialFactory mSerialFactory; }; -} +unsigned int GetBlendSampleMask(const gl::State &glState, int samples); +bool InstancedPointSpritesActive(ProgramD3D *programD3D, GLenum mode); + +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h index 7aabdc8132..3f8f5b9d8d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h @@ -17,7 +17,7 @@ namespace rx class SamplerD3D : public SamplerImpl { public: - SamplerD3D() {} + SamplerD3D(const gl::SamplerState &state) : SamplerImpl(state) {} ~SamplerD3D() override {} }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp index 1ecbfb7410..2a8f1fb11c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -9,9 +9,11 @@ #include "libANGLE/renderer/d3d/ShaderD3D.h" #include "common/utilities.h" +#include "libANGLE/Caps.h" #include "libANGLE/Compiler.h" #include "libANGLE/Shader.h" #include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" // Definitions local to the translation unit @@ -28,6 +30,9 @@ const char *GetShaderTypeString(GLenum type) case GL_FRAGMENT_SHADER: return "FRAGMENT"; + case GL_COMPUTE_SHADER: + return "COMPUTE"; + default: UNREACHABLE(); return ""; @@ -39,9 +44,39 @@ const char *GetShaderTypeString(GLenum type) namespace rx { -ShaderD3D::ShaderD3D(const gl::Shader::Data &data) : ShaderImpl(data) +ShaderD3D::ShaderD3D(const gl::ShaderState &data, + const angle::WorkaroundsD3D &workarounds, + const gl::Extensions &extensions) + : 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; + } + if (extensions.multiview) + { + mAdditionalOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW; + } } ShaderD3D::~ShaderD3D() @@ -50,6 +85,11 @@ ShaderD3D::~ShaderD3D() std::string ShaderD3D::getDebugInfo() const { + if (mDebugInfo.empty()) + { + return ""; + } + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER END\n"; } @@ -69,15 +109,16 @@ void ShaderD3D::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; + mHasANGLEMultiviewEnabled = false; + mUsesViewID = false; mUsesDiscardRewriting = false; mUsesNestedBreak = false; - mUsesDeferredInit = false; mRequiresIEEEStrictCompiling = false; mDebugInfo.clear(); } -void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const +void ShaderD3D::generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const { if (mUsesDiscardRewriting) { @@ -106,10 +147,10 @@ unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const return mUniformRegisterMap.find(uniformName)->second; } -unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const +unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const { - ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); - return mInterfaceBlockRegisterMap.find(blockName)->second; + ASSERT(mUniformBlockRegisterMap.count(blockName) > 0); + return mUniformBlockRegisterMap.find(blockName)->second; } ShShaderOutput ShaderD3D::getCompilerOutputType() const @@ -117,12 +158,12 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const return mCompilerOutputType; } -int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream, - std::string *sourcePath) +ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream, + std::string *sourcePath) { uncompile(); - int additionalOptions = 0; + ShCompileOptions additionalOptions = 0; const std::string &source = mData.getSource(); @@ -135,10 +176,24 @@ int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStre } #endif + additionalOptions |= mAdditionalOptions; + *shaderSourceStream << source; return additionalOptions; } +bool ShaderD3D::hasUniform(const std::string &name) const +{ + return mUniformRegisterMap.find(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. @@ -154,41 +209,30 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo 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; + mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mHasANGLEMultiviewEnabled = + translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos; + mUsesViewID = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos; mUsesDiscardRewriting = translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; - mUsesDeferredInit = translatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos; mRequiresIEEEStrictCompiling = translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType()); - for (const sh::Uniform &uniform : mData.getUniforms()) - { - if (uniform.staticUse && !uniform.isBuiltIn()) - { - unsigned int index = static_cast<unsigned int>(-1); - bool getUniformRegisterResult = - ShGetUniformRegister(compilerHandle, uniform.name, &index); - UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); - ASSERT(getUniformRegisterResult); - - mUniformRegisterMap[uniform.name] = index; - } - } + mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle)); - for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks()) + for (const sh::InterfaceBlock &interfaceBlock : mData.getUniformBlocks()) { if (interfaceBlock.staticUse) { unsigned int index = static_cast<unsigned int>(-1); bool blockRegisterResult = - ShGetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index); - UNUSED_ASSERTION_VARIABLE(blockRegisterResult); + sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index); ASSERT(blockRegisterResult); - mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + mUniformBlockRegisterMap[interfaceBlock.name] = index; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h index 47a73dc27b..f7b0b20db4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -13,31 +13,50 @@ #include <map> +namespace angle +{ +struct CompilerWorkaroundsD3D; +struct WorkaroundsD3D; +} + +namespace gl +{ +struct Extensions; +} + namespace rx { class DynamicHLSL; class RendererD3D; -struct D3DCompilerWorkarounds; +struct D3DUniform; class ShaderD3D : public ShaderImpl { public: - ShaderD3D(const gl::Shader::Data &data); - virtual ~ShaderD3D(); + ShaderD3D(const gl::ShaderState &data, + const angle::WorkaroundsD3D &workarounds, + const gl::Extensions &extensions); + ~ShaderD3D() override; // ShaderImpl implementation - int prepareSourceAndReturnOptions(std::stringstream *sourceStream, - std::string *sourcePath) override; + 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 std::string &name) 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; + + unsigned int getUniformBlockRegister(const std::string &blockName) const; void appendDebugInfo(const std::string &info) const { mDebugInfo += info; } - void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; + void generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const; bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; } bool usesFragColor() const { return mUsesFragColor; } @@ -48,7 +67,8 @@ class ShaderD3D : public ShaderImpl bool usesPointCoord() const { return mUsesPointCoord; } bool usesDepthRange() const { return mUsesDepthRange; } bool usesFragDepth() const { return mUsesFragDepth; } - bool usesDeferredInit() const { return mUsesDeferredInit; } + bool usesViewID() const { return mUsesViewID; } + bool hasANGLEMultiviewEnabled() const { return mHasANGLEMultiviewEnabled; } ShShaderOutput getCompilerOutputType() const; @@ -62,16 +82,18 @@ class ShaderD3D : public ShaderImpl bool mUsesPointCoord; bool mUsesDepthRange; bool mUsesFragDepth; + bool mHasANGLEMultiviewEnabled; + bool mUsesViewID; bool mUsesDiscardRewriting; bool mUsesNestedBreak; - bool mUsesDeferredInit; bool mRequiresIEEEStrictCompiling; ShShaderOutput mCompilerOutputType; mutable std::string mDebugInfo; std::map<std::string, unsigned int> mUniformRegisterMap; - std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; + std::map<std::string, unsigned int> mUniformBlockRegisterMap; + ShCompileOptions mAdditionalOptions; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp index 97ffdf5094..83a66bd1a5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp @@ -44,9 +44,13 @@ void ShaderExecutableD3D::appendDebugInfo(const std::string &info) mDebugInfo += info; } - -UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize) +UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mUniformData() { + bool result = mUniformData.resize(initialSize); + ASSERT(result); + + // Uniform data is zero-initialized by default. + mUniformData.fill(0); } UniformStorageD3D::~UniformStorageD3D() @@ -55,7 +59,13 @@ UniformStorageD3D::~UniformStorageD3D() size_t UniformStorageD3D::size() const { - return mSize; + return mUniformData.size(); } +uint8_t *UniformStorageD3D::getDataPointer(unsigned int registerIndex, unsigned int registerElement) +{ + size_t offset = ((registerIndex * 4 + registerElement) * sizeof(float)); + return mUniformData.data() + offset; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h index 71b83b7954..b8097710e2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h @@ -10,6 +10,7 @@ #ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ #define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ +#include "common/MemoryBuffer.h" #include "common/debug.h" #include <vector> @@ -45,10 +46,12 @@ class UniformStorageD3D : angle::NonCopyable size_t size() const; + uint8_t *getDataPointer(unsigned int registerIndex, unsigned int registerElement); + private: - size_t mSize; + angle::MemoryBuffer mUniformData; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index f567f47525..7657aef79e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -8,10 +8,11 @@ #include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/Context.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/RendererD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h" #include <tchar.h> @@ -21,60 +22,62 @@ namespace rx { -SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, - EGLint width, EGLint height) -{ - return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, EGL_FALSE, - shareHandle, NULL); -} - -SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, - egl::Display *display, - const egl::Config *config, - EGLNativeWindowType window, - EGLint fixedSize, - EGLint directComposition, - EGLint width, - EGLint height, - EGLint orientation) -{ - return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation, - directComposition, static_cast<EGLClientBuffer>(0), window); -} - -SurfaceD3D::SurfaceD3D(RendererD3D *renderer, +SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, egl::Display *display, - const egl::Config *config, - EGLint width, - EGLint height, - EGLint fixedSize, - EGLint orientation, - EGLint directComposition, - EGLClientBuffer shareHandle, - EGLNativeWindowType window) - : SurfaceImpl(), + EGLNativeWindowType window, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) + : SurfaceImpl(state), mRenderer(renderer), mDisplay(display), - mFixedSize(fixedSize == EGL_TRUE), - mOrientation(orientation), - mRenderTargetFormat(config->renderTargetFormat), - mDepthStencilFormat(config->depthStencilFormat), + 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(state.config->renderTargetFormat), + mDepthStencilFormat(state.config->depthStencilFormat), mSwapChain(nullptr), mSwapIntervalDirty(true), mWindowSubclassed(false), - mNativeWindow(window, config, directComposition == EGL_TRUE), - mWidth(width), - mHeight(height), + mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)), + mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))), + mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))), mSwapInterval(1), - mShareHandle(reinterpret_cast<HANDLE *>(shareHandle)) + mShareHandle(0), + mD3DTexture(nullptr) { subclassWindow(); + 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(); + ANGLE_SWALLOW_ERR(mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth, + &mHeight, &mRenderTargetFormat)); + break; + + default: + break; + } } SurfaceD3D::~SurfaceD3D() { unsubclassWindow(); releaseSwapChain(); + SafeDelete(mNativeWindow); + SafeRelease(mD3DTexture); } void SurfaceD3D::releaseSwapChain() @@ -82,41 +85,41 @@ void SurfaceD3D::releaseSwapChain() SafeDelete(mSwapChain); } -egl::Error SurfaceD3D::initialize() +egl::Error SurfaceD3D::initialize(const egl::Display *display) { - if (mNativeWindow.getNativeWindow()) + if (mNativeWindow->getNativeWindow()) { - if (!mNativeWindow.initialize()) + if (!mNativeWindow->initialize()) { - return egl::Error(EGL_BAD_SURFACE); + return egl::EglBadSurface(); } } - egl::Error error = resetSwapChain(); - if (error.isError()) - { - return error; - } - - return egl::Error(EGL_SUCCESS); + ANGLE_TRY(resetSwapChain(display)); + return egl::NoError(); } -FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data) { - return mRenderer->createFramebuffer(data); + return mRenderer->createDefaultFramebuffer(data); } egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint) { - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } egl::Error SurfaceD3D::releaseTexImage(EGLint) { - return egl::Error(EGL_SUCCESS); + return egl::NoError(); +} + +egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) +{ + return mSwapChain->getSyncValues(ust, msc, sbc); } -egl::Error SurfaceD3D::resetSwapChain() +egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display) { ASSERT(!mSwapChain); @@ -126,11 +129,11 @@ egl::Error SurfaceD3D::resetSwapChain() if (!mFixedSize) { RECT windowRect; - if (!mNativeWindow.getClientRect(&windowRect)) + if (!mNativeWindow->getClientRect(&windowRect)) { ASSERT(false); - return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); + return egl::EglBadSurface() << "Could not retrieve the window dimensions"; } width = windowRect.right - windowRect.left; @@ -143,29 +146,34 @@ egl::Error SurfaceD3D::resetSwapChain() height = mHeight; } - mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, - mDepthStencilFormat, mOrientation); + mSwapChain = + mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat, + mDepthStencilFormat, mOrientation, mState.config->samples); if (!mSwapChain) { - return egl::Error(EGL_BAD_ALLOC); + return egl::EglBadAlloc(); } - egl::Error error = resetSwapChain(width, height); + // This is a bit risky to pass the proxy context here, but it can happen at almost any time. + egl::Error error = resetSwapChain(display->getProxyContext(), width, height); if (error.isError()) { SafeDelete(mSwapChain); return error; } - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight) +egl::Error SurfaceD3D::resizeSwapChain(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); + EGLint status = + mSwapChain->resize(context, std::max(1, backbufferWidth), std::max(1, backbufferHeight)); if (status == EGL_CONTEXT_LOST) { @@ -180,15 +188,18 @@ egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight mWidth = backbufferWidth; mHeight = backbufferHeight; - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) +egl::Error SurfaceD3D::resetSwapChain(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); + EGLint status = mSwapChain->reset(context, std::max(1, backbufferWidth), + std::max(1, backbufferHeight), mSwapInterval); if (status == EGL_CONTEXT_LOST) { @@ -204,17 +215,20 @@ egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) mHeight = backbufferHeight; mSwapIntervalDirty = false; - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +egl::Error SurfaceD3D::swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: eglPostSubBufferNV comes here if (x + width > mWidth) { width = mWidth - x; @@ -224,11 +238,10 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { height = mHeight - y; } -#endif if (width != 0 && height != 0) { - EGLint status = mSwapChain->swapRect(x, y, width, height); + EGLint status = mSwapChain->swapRect(context, x, y, width, height); if (status == EGL_CONTEXT_LOST) { @@ -241,34 +254,36 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) } } - checkForOutOfDateSwapChain(); + ANGLE_TRY(checkForOutOfDateSwapChain(context)); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") +#define kDisplayProperty _TEXT("Egl::Display") static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - if (message == WM_SIZE) - { - SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty)); - if(surf) - { - surf->checkForOutOfDateSwapChain(); - } - } - WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); - return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); + if (message == WM_SIZE) + { + SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + egl::Display *display = reinterpret_cast<egl::Display *>(GetProp(hwnd, kDisplayProperty)); + surf->checkForOutOfDateSwapChain(display->getProxyContext()); + } + } + WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); } #endif void SurfaceD3D::subclassWindow() { #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); + HWND window = mNativeWindow->getNativeWindow(); if (!window) { return; @@ -291,6 +306,7 @@ void SurfaceD3D::subclassWindow() SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + SetProp(window, kDisplayProperty, reinterpret_cast<HANDLE>(mDisplay)); mWindowSubclassed = true; #endif } @@ -303,7 +319,7 @@ void SurfaceD3D::unsubclassWindow() } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); + HWND window = mNativeWindow->getNativeWindow(); if (!window) { return; @@ -320,30 +336,31 @@ void SurfaceD3D::unsubclassWindow() if(parentWndFunc) { LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); - UNUSED_ASSERTION_VARIABLE(prevWndFunc); ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); } RemoveProp(window, kSurfaceProperty); RemoveProp(window, kParentWndProc); + RemoveProp(window, kDisplayProperty); #endif mWindowSubclassed = false; } -bool SurfaceD3D::checkForOutOfDateSwapChain() + +egl::Error SurfaceD3D::checkForOutOfDateSwapChain(const gl::Context *context) { RECT client; int clientWidth = getWidth(); int clientHeight = getHeight(); bool sizeDirty = false; - if (!mFixedSize && !mNativeWindow.isIconic()) + 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)) + if (!mNativeWindow->getClientRect(&client)) { - ASSERT(false); - return false; + UNREACHABLE(); + return egl::NoError(); } // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. @@ -352,28 +369,30 @@ bool SurfaceD3D::checkForOutOfDateSwapChain() sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); } - bool wasDirty = (mSwapIntervalDirty || sizeDirty); - if (mSwapIntervalDirty) { - resetSwapChain(clientWidth, clientHeight); + ANGLE_TRY(resetSwapChain(context, clientWidth, clientHeight)); } else if (sizeDirty) { - resizeSwapChain(clientWidth, clientHeight); + ANGLE_TRY(resizeSwapChain(context, clientWidth, clientHeight)); } - return wasDirty; + return egl::NoError(); } -egl::Error SurfaceD3D::swap() +egl::Error SurfaceD3D::swap(const gl::Context *context) { - return swapRect(0, 0, mWidth, mHeight); + return swapRect(context, 0, 0, mWidth, mHeight); } -egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +egl::Error SurfaceD3D::postSubBuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { - return swapRect(x, y, width, height); + return swapRect(context, x, y, width, height); } rx::SwapChainD3D *SurfaceD3D::getSwapChain() const @@ -429,13 +448,15 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) } else UNREACHABLE(); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } -gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, +gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) { - if (target.binding() == GL_BACK) + if (binding == GL_BACK) { *rtOut = mSwapChain->getColorRenderTarget(); } @@ -443,7 +464,46 @@ gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment: { *rtOut = mSwapChain->getDepthStencilRenderTarget(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) + : SurfaceD3D(state, + renderer, + display, + window, + 0, + static_cast<EGLClientBuffer>(0), + attribs) +{ +} + +WindowSurfaceD3D::~WindowSurfaceD3D() +{ } +PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) + : SurfaceD3D(state, + renderer, + display, + static_cast<EGLNativeWindowType>(0), + buftype, + clientBuffer, + attribs) +{ } + +PbufferSurfaceD3D::~PbufferSurfaceD3D() +{ +} + +} // namespace rc diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h index 67d408ddd9..01d2573244 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -10,7 +10,7 @@ #define LIBANGLE_RENDERER_D3D_SURFACED3D_H_ #include "libANGLE/renderer/SurfaceImpl.h" -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" namespace egl { @@ -25,28 +25,22 @@ class RendererD3D; class SurfaceD3D : public SurfaceImpl { public: - static SurfaceD3D *createFromWindow(RendererD3D *renderer, - egl::Display *display, - const egl::Config *config, - EGLNativeWindowType window, - EGLint fixedSize, - EGLint directComposition, - EGLint width, - EGLint height, - EGLint orientation); - static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, - EGLClientBuffer shareHandle, EGLint width, EGLint height); ~SurfaceD3D() override; void releaseSwapChain(); - egl::Error initialize() override; - FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; + egl::Error initialize(const egl::Display *display) 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 swap(const gl::Context *context) override; + egl::Error postSubBuffer(const gl::Context *context, + 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; + egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; void setSwapInterval(EGLint interval) override; EGLint getWidth() const override; @@ -58,29 +52,35 @@ class SurfaceD3D : public SurfaceImpl // D3D implementations SwapChainD3D *getSwapChain() const; - egl::Error resetSwapChain(); + egl::Error resetSwapChain(const egl::Display *display); - // Returns true if swapchain changed due to resize or interval update - bool checkForOutOfDateSwapChain(); + egl::Error checkForOutOfDateSwapChain(const gl::Context *context); - gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + gl::Error getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) override; - private: - SurfaceD3D(RendererD3D *renderer, + protected: + SurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, egl::Display *display, - const egl::Config *config, - EGLint width, - EGLint height, - EGLint fixedSize, - EGLint orientation, - EGLint directComposition, - EGLClientBuffer shareHandle, - EGLNativeWindowType window); - - 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); + EGLNativeWindowType window, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs); + + egl::Error swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height); + egl::Error resetSwapChain(const gl::Context *context, + int backbufferWidth, + int backbufferHeight); + egl::Error resizeSwapChain(const gl::Context *context, + int backbufferWidth, + int backbufferHeight); void subclassWindow(); void unsubclassWindow(); @@ -96,18 +96,41 @@ class SurfaceD3D : public SurfaceImpl SwapChainD3D *mSwapChain; bool mSwapIntervalDirty; - bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking - NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. + 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, + EGLNativeWindowType window, + const egl::AttributeMap &attribs); + ~WindowSurfaceD3D() override; +}; -} +class PbufferSurfaceD3D : public SurfaceD3D +{ + public: + PbufferSurfaceD3D(const egl::SurfaceState &state, + RendererD3D *renderer, + egl::Display *display, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs); + ~PbufferSurfaceD3D() override; +}; + +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp new file mode 100644 index 0000000000..de8534c3da --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h index 171cab54dd..017737b878 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h @@ -12,17 +12,26 @@ #include <GLES2/gl2.h> #include <EGL/egl.h> +#include <EGL/eglext.h> #include "common/angleutils.h" #include "common/platform.h" - -// TODO: move out of D3D11 -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/Error.h" #if !defined(ANGLE_FORCE_VSYNC_OFF) #define ANGLE_FORCE_VSYNC_OFF 0 #endif +namespace gl +{ +class Context; +} // namespace gl + +namespace egl +{ +class Display; +} // namespace egl + namespace rx { class RenderTargetD3D; @@ -30,35 +39,45 @@ class RenderTargetD3D; class SwapChainD3D : angle::NonCopyable { public: - SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mNativeWindow(nativeWindow), mOffscreenRenderTargetFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat), mShareHandle(shareHandle) - { - } - - 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; + SwapChainD3D(HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat); + virtual ~SwapChainD3D(); + + virtual EGLint resize(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferSize) = 0; + virtual EGLint reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) = 0; + virtual EGLint swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) = 0; virtual void recreate() = 0; - virtual void *getDevice() { return NULL; } + virtual void *getDevice() { return nullptr; } virtual RenderTargetD3D *getColorRenderTarget() = 0; virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; - GLenum GetRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; } - GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } + GLenum getRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; } + GLenum getDepthBufferInternalFormat() const { return mDepthBufferFormat; } HANDLE getShareHandle() { return mShareHandle; } virtual void *getKeyedMutex() = 0; + virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0; + protected: - rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. const GLenum mOffscreenRenderTargetFormat; const GLenum mDepthBufferFormat; HANDLE mShareHandle; + IUnknown *mD3DTexture; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp index 430576b318..bf44cbb5d2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -12,6 +12,7 @@ #include "common/utilities.h" #include "libANGLE/Buffer.h" #include "libANGLE/Config.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/Image.h" #include "libANGLE/Surface.h" @@ -21,8 +22,8 @@ #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/RendererD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/TextureStorage.h" @@ -32,26 +33,24 @@ namespace rx namespace { -gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels, - ptrdiff_t layerOffset, const uint8_t **pointerOut) +gl::Error GetUnpackPointer(const gl::Context *context, + const gl::PixelUnpackState &unpack, + gl::Buffer *unpackBuffer, + const uint8_t *pixels, + ptrdiff_t layerOffset, + const uint8_t **pointerOut) { - if (unpack.pixelBuffer.id() != 0) + if (unpackBuffer) { // 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); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(unpackBuffer); ASSERT(bufferD3D); - const uint8_t *bufferData = NULL; - gl::Error error = bufferD3D->getData(&bufferData); - if (error.isError()) - { - return error; - } - + const uint8_t *bufferData = nullptr; + ANGLE_TRY(bufferD3D->getData(context, &bufferData)); *pointerOut = bufferData + offset; } else @@ -65,7 +64,7 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pi *pointerOut += layerOffset; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool IsRenderTargetUsage(GLenum usage) @@ -75,41 +74,66 @@ bool IsRenderTargetUsage(GLenum usage) } -TextureD3D::TextureD3D(RendererD3D *renderer) - : mRenderer(renderer), - mUsage(GL_NONE), +TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer) + : TextureImpl(state), + mRenderer(renderer), mDirtyImages(true), mImmutable(false), - mTexStorage(NULL) + mTexStorage(nullptr), + mBaseLevel(0) { } TextureD3D::~TextureD3D() { + ASSERT(!mTexStorage); } -gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage) +gl::Error TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage) { // ensure the underlying texture is created - gl::Error error = initializeStorage(false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initializeStorage(context, false)); if (mTexStorage) { - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); } ASSERT(outStorage); *outStorage = mTexStorage; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error TextureD3D::getImageAndSyncFromStorage(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D **outImage) +{ + ImageD3D *image = getImage(index); + if (mTexStorage && mTexStorage->isRenderTarget()) + { + ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage)); + mDirtyImages = true; + } + *outImage = image; + 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 @@ -139,6 +163,27 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const return (baseImage ? baseImage->getInternalFormat() : GL_NONE); } +gl::Error TextureD3D::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D::setStorageMultisample(const gl::Context *context, + GLenum target, + GLsizei samples, + GLint internalFormat, + const gl::Extents &size, + bool fixedSampleLocations) +{ + UNREACHABLE(); + return gl::InternalError(); +} + bool TextureD3D::shouldUseSetData(const ImageD3D *image) const { if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) @@ -146,7 +191,12 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const return false; } - gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat()); + if (image->isDirty()) + { + return false; + } + + gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat()); // We can only handle full updates for depth-stencil textures, so to avoid complications // disable them entirely. @@ -159,173 +209,166 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const return (mTexStorage && !internalFormat.compressed); } -gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index, +gl::Error TextureD3D::setImageImpl(const gl::Context *context, + const gl::ImageIndex &index, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) { ImageD3D *image = getImage(index); + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); ASSERT(image); // No-op if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) { - return gl::Error(GL_NO_ERROR); + 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; - gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); - if (error.isError()) - { - return error; - } + const uint8_t *pixelData = nullptr; + ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData)); if (pixelData != nullptr) { if (shouldUseSetData(image)) { - error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData); + ANGLE_TRY( + mTexStorage->setData(context, index, image, nullptr, type, unpack, pixelData)); } else { gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); - error = image->loadData(fullImageArea, unpack, type, pixelData); - } - - if (error.isError()) - { - return error; + ANGLE_TRY( + image->loadData(context, fullImageArea, unpack, type, pixelData, index.is3D())); } mDirtyImages = true; } - return gl::Error(GL_NO_ERROR); + 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) +gl::Error TextureD3D::subImage(const gl::Context *context, + 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; - gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); - if (error.isError()) - { - return error; - } + const uint8_t *pixelData = nullptr; + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData)); - if (pixelData != NULL) + if (pixelData != nullptr) { ImageD3D *image = getImage(index); ASSERT(image); if (shouldUseSetData(image)) { - return mTexStorage->setData(index, image, &area, type, unpack, pixelData); - } - - error = image->loadData(area, unpack, type, pixelData); - if (error.isError()) - { - return error; - } - - error = commitRegion(index, area); - if (error.isError()) - { - return error; + return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData); } + ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.is3D())); + ANGLE_TRY(commitRegion(context, index, area)); mDirtyImages = true; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index, +gl::Error TextureD3D::setCompressedImageImpl(const gl::Context *context, + const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) { - // 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; - gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); - if (error.isError()) + ImageD3D *image = getImage(index); + ASSERT(image); + + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) { - return error; + return gl::NoError(); } - if (pixelData != NULL) - { - ImageD3D *image = getImage(index); - ASSERT(image); + // 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 = nullptr; + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData)); + if (pixelData != nullptr) + { gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); - error = image->loadCompressedData(fullImageArea, pixelData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(image->loadCompressedData(context, fullImageArea, pixelData)); mDirtyImages = true; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels, +gl::Error TextureD3D::subImageCompressed(const gl::Context *context, + 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; - gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); - if (error.isError()) - { - return error; - } + const uint8_t *pixelData = nullptr; + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData)); - if (pixelData != NULL) + if (pixelData != nullptr) { ImageD3D *image = getImage(index); ASSERT(image); - error = image->loadCompressedData(area, pixelData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(image->loadCompressedData(context, area, pixelData)); mDirtyImages = true; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +bool TextureD3D::isFastUnpackable(const gl::Buffer *unpackBuffer, GLenum sizedInternalFormat) { - return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); + return unpackBuffer != nullptr && + 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) +gl::Error TextureD3D::fastUnpackPixels(const gl::Context *context, + 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"); + return gl::InternalError() << "Unimplemented pixel store parameters in fastUnpackPixels"; } // No-op if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // In order to perform the fast copy through the shader, we must have the right format, and be able @@ -334,18 +377,17 @@ gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uintptr_t offset = reinterpret_cast<uintptr_t>(pixels); - gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, static_cast<unsigned int>(offset), destRenderTarget, sizedInternalFormat, type, destArea); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->fastCopyBufferToTexture(context, unpack, static_cast<unsigned int>(offset), + destRenderTarget, sizedInternalFormat, type, + destArea)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const { - if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) + 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; @@ -357,11 +399,6 @@ GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) c } } -int TextureD3D::mipLevels() const -{ - return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; -} - TextureStorage *TextureD3D::getStorage() { ASSERT(mTexStorage); @@ -370,72 +407,60 @@ TextureStorage *TextureD3D::getStorage() ImageD3D *TextureD3D::getBaseLevelImage() const { - return getImage(getImageIndex(0, 0)); + if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return nullptr; + } + return getImage(getImageIndex(mBaseLevel, 0)); } -gl::Error TextureD3D::generateMipmaps(const gl::TextureState &textureState) +gl::Error TextureD3D::setImageExternal(const gl::Context *context, + GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) { - GLint mipCount = mipLevels(); + // Only external images can accept external textures + UNREACHABLE(); + return gl::InternalError(); +} - if (mipCount == 1) - { - return gl::Error(GL_NO_ERROR); // no-op - } +gl::Error TextureD3D::generateMipmap(const gl::Context *context) +{ + 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; - gl::Error error = getNativeTexture(&textureStorage); - if (error.isError()) - { - return error; - } - - error = textureStorage->useLevelZeroWorkaroundTexture(false); - if (error.isError()) - { - return error; - } + TextureStorage *textureStorage = nullptr; + ANGLE_TRY(getNativeTexture(context, &textureStorage)); + ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(context, false)); } // Set up proper mipmap chain in our Image array. - initMipmapsImages(); + ANGLE_TRY(initMipmapImages(context)); if (mTexStorage && mTexStorage->supportsNativeMipmapFunction()) { - gl::Error error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); // Generate the mipmap chain using the ad-hoc DirectX function. - error = mRenderer->generateMipmapsUsingD3D(mTexStorage, textureState); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->generateMipmapUsingD3D(context, mTexStorage, mState)); } else { // Generate the mipmap chain, one level at a time. - gl::Error error = generateMipmapsUsingImages(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(generateMipmapUsingImages(context, maxLevel)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D::generateMipmapsUsingImages() +gl::Error TextureD3D::generateMipmapUsingImages(const gl::Context *context, const GLuint maxLevel) { - GLint mipCount = mipLevels(); - // We know that all layers have the same dimension, for the texture to be complete - GLint layerCount = static_cast<GLint>(getLayerCount(0)); + 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 @@ -447,23 +472,15 @@ gl::Error TextureD3D::generateMipmapsUsingImages() // Copy from the storage mip 0 to Image mip 0 for (GLint layer = 0; layer < layerCount; ++layer) { - gl::ImageIndex srcIndex = getImageIndex(0, layer); + gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer); ImageD3D *image = getImage(srcIndex); - gl::Error error = image->copyFromTexStorage(srcIndex, mTexStorage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(image->copyFromTexStorage(context, srcIndex, mTexStorage)); } } else { - gl::Error error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); } } @@ -476,7 +493,7 @@ gl::Error TextureD3D::generateMipmapsUsingImages() for (GLint layer = 0; layer < layerCount; ++layer) { - for (GLint mip = 1; mip < mipCount; ++mip) + for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip) { ASSERT(getLayerCount(mip) == layerCount); @@ -486,30 +503,25 @@ gl::Error TextureD3D::generateMipmapsUsingImages() if (renderableStorage) { // GPU-side mipmapping - gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mTexStorage->generateMipmap(context, sourceIndex, destIndex)); } else { // CPU-side mipmapping - gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)); - if (error.isError()) - { - return error; - } + ANGLE_TRY( + mRenderer->generateMipmap(context, getImage(destIndex), getImage(sourceIndex))); } } } + mDirtyImages = true; + if (mTexStorage) { - updateStorage(); + ANGLE_TRY(updateStorage(context)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool TextureD3D::isBaseImageZeroSize() const @@ -531,7 +543,7 @@ bool TextureD3D::isBaseImageZeroSize() const return true; } - if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0) + if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0) { return true; } @@ -539,12 +551,16 @@ bool TextureD3D::isBaseImageZeroSize() const return false; } -gl::Error TextureD3D::ensureRenderTarget() +gl::Error TextureD3D::ensureRenderTarget(const gl::Context *context) { - gl::Error error = initializeStorage(true); - if (error.isError()) + ANGLE_TRY(initializeStorage(context, true)); + + // initializeStorage can fail with NoError if the texture is not complete. This is not + // an error for incomplete sampling, but it is a big problem for rendering. + if (!mTexStorage) { - return error; + UNREACHABLE(); + return gl::InternalError() << "Cannot render to incomplete texture."; } if (!isBaseImageZeroSize()) @@ -552,94 +568,210 @@ gl::Error TextureD3D::ensureRenderTarget() ASSERT(mTexStorage); if (!mTexStorage->isRenderTarget()) { - TextureStorage *newRenderTargetStorage = NULL; - error = createCompleteStorage(true, &newRenderTargetStorage); - if (error.isError()) - { - return error; - } + TexStoragePointer newRenderTargetStorage(context); + ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage)); - error = mTexStorage->copyToStorage(newRenderTargetStorage); - if (error.isError()) - { - SafeDelete(newRenderTargetStorage); - return error; - } - - error = setCompleteTexStorage(newRenderTargetStorage); - if (error.isError()) - { - SafeDelete(newRenderTargetStorage); - return error; - } + ANGLE_TRY(mTexStorage->copyToStorage(context, newRenderTargetStorage.get())); + ANGLE_TRY(setCompleteTexStorage(context, newRenderTargetStorage.get())); + newRenderTargetStorage.release(); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const { + if (index.type == GL_TEXTURE_2D_MULTISAMPLE) + return true; + ImageD3D *image = getImage(index); + ASSERT(image); bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); return (image->isRenderableFormat() && levelsComplete); } -gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error TextureD3D::commitRegion(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Box ®ion) { if (mTexStorage) { ASSERT(isValidIndex(index)); ImageD3D *image = getImage(index); - gl::Error error = image->copyToStorage(mTexStorage, index, region); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(image->copyToStorage(context, mTexStorage, index, region)); image->markClean(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, +gl::Error TextureD3D::getAttachmentRenderTarget(const gl::Context *context, + GLenum /*binding*/, + const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) { RenderTargetD3D *rtD3D = nullptr; - gl::Error error = getRenderTarget(target.textureIndex(), &rtD3D); + gl::Error error = getRenderTarget(context, imageIndex, &rtD3D); *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D); return error; } -TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) - : TextureD3D(renderer) +gl::Error TextureD3D::setBaseLevel(const gl::Context *context, 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(); + ANGLE_TRY(releaseTexStorage(context)); + } + + return gl::NoError(); +} + +void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits) +{ + // TODO(geofflang): Use dirty bits +} + +gl::Error TextureD3D::releaseTexStorage(const gl::Context *context) +{ + if (!mTexStorage) + { + return gl::NoError(); + } + auto err = mTexStorage->onDestroy(context); + SafeDelete(mTexStorage); + return err; +} + +gl::Error TextureD3D::onDestroy(const gl::Context *context) +{ + return releaseTexStorage(context); +} + +gl::Error TextureD3D::initializeContents(const gl::Context *context, + const gl::ImageIndex &imageIndexIn) +{ + gl::ImageIndex imageIndex = imageIndexIn; + + // Special case for D3D11 3D textures. We can't create render targets for individual layers of a + // 3D texture, so force the clear to the entire mip. There shouldn't ever be a case where we + // would lose existing data. + if (imageIndex.type == GL_TEXTURE_3D) + { + imageIndex.layerIndex = gl::ImageIndex::ENTIRE_LEVEL; + } + else if (imageIndex.type == GL_TEXTURE_2D_ARRAY && + imageIndex.layerIndex == gl::ImageIndex::ENTIRE_LEVEL) + { + GLsizei layerCount = getLayerCount(imageIndex.mipIndex); + for (imageIndex.layerIndex = 0; imageIndex.layerIndex < layerCount; ++imageIndex.layerIndex) + { + ANGLE_TRY(initializeContents(context, imageIndex)); + } + return gl::NoError(); + } + + // Force image clean. + ImageD3D *image = getImage(imageIndex); + if (image) + { + image->markClean(); + } + + // Fast path: can use a render target clear. + if (canCreateRenderTargetForImage(imageIndex)) + { + ANGLE_TRY(ensureRenderTarget(context)); + ASSERT(mTexStorage); + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(mTexStorage->getRenderTarget(context, imageIndex, &renderTarget)); + ANGLE_TRY(mRenderer->initRenderTarget(renderTarget)); + return gl::NoError(); + } + + // Slow path: non-renderable texture or the texture levels aren't set up. + const auto &formatInfo = gl::GetSizedInternalFormatInfo(image->getInternalFormat()); + + size_t imageBytes = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(formatInfo.type, image->getWidth(), 1, 0), + imageBytes); + imageBytes *= image->getHeight() * image->getDepth(); + + gl::PixelUnpackState defaultUnpackState; + + angle::MemoryBuffer *zeroBuffer = nullptr; + ANGLE_TRY(context->getZeroFilledBuffer(imageBytes, &zeroBuffer)); + if (shouldUseSetData(image)) + { + ANGLE_TRY(mTexStorage->setData(context, imageIndex, image, nullptr, formatInfo.type, + defaultUnpackState, zeroBuffer->data())); + } + else + { + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + ANGLE_TRY(image->loadData(context, fullImageArea, defaultUnpackState, formatInfo.type, + zeroBuffer->data(), false)); + + // Force an update to the tex storage so we avoid problems with subImage and dirty regions. + if (mTexStorage) + { + ANGLE_TRY(commitRegion(context, imageIndex, fullImageArea)); + image->markClean(); + } + else + { + mDirtyImages = true; + } + } + return gl::NoError(); +} + +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) + for (auto &image : mImageArray) { - mImageArray[i] = renderer->createImage(); + image.reset(renderer->createImage()); } } -TextureD3D_2D::~TextureD3D_2D() +gl::Error TextureD3D_2D::onDestroy(const gl::Context *context) { - // 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 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 (auto &image : mImageArray) { - delete mImageArray[i]; + image.reset(); } + return TextureD3D::onDestroy(context); +} - SafeDelete(mTexStorage); +TextureD3D_2D::~TextureD3D_2D() +{ } ImageD3D *TextureD3D_2D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(layer == 0); - return mImageArray[level]; + return mImageArray[level].get(); } ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const @@ -647,7 +779,7 @@ 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]; + return mImageArray[index.mipIndex].get(); } GLsizei TextureD3D_2D::getLayerCount(int level) const @@ -682,10 +814,16 @@ GLenum TextureD3D_2D::getInternalFormat(GLint level) const bool TextureD3D_2D::isDepth(GLint level) const { - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; + return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +bool TextureD3D_2D::isSRGB(GLint level) const +{ + return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB; } -gl::Error TextureD3D_2D::setImage(GLenum target, +gl::Error TextureD3D_2D::setImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -696,33 +834,29 @@ gl::Error TextureD3D_2D::setImage(GLenum target, { ASSERT(target == GL_TEXTURE_2D && size.depth == 1); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); bool fastUnpacked = false; GLint level = static_cast<GLint>(imageLevel); - redefineImage(level, sizedInternalFormat, size, false); + ANGLE_TRY(redefineImage(context, level, internalFormatInfo.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)) + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && + isLevelComplete(level)) { // Will try to create RT storage if it does not exist - RenderTargetD3D *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget)); gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); - error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea, + internalFormatInfo.sizedInternalFormat, type, destRenderTarget)); // Ensure we don't overwrite our newly initialized data mImageArray[level]->markClean(); @@ -732,17 +866,14 @@ gl::Error TextureD3D_2D::setImage(GLenum target, if (!fastUnpacked) { - gl::Error error = setImageImpl(index, type, unpack, pixels, 0); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2D::setSubImage(GLenum target, +gl::Error TextureD3D_2D::setSubImage(const gl::Context *context, + GLenum target, size_t imageLevel, const gl::Box &area, GLenum format, @@ -754,26 +885,26 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target, GLint level = static_cast<GLint>(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2D(level); - if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) - { - RenderTargetD3D *renderTarget = NULL; - gl::Error error = getRenderTarget(index, &renderTarget); - if (error.isError()) - { - return error; - } + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + if (isFastUnpackable(unpackBuffer, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTargetD3D *renderTarget = nullptr; + ANGLE_TRY(getRenderTarget(context, index, &renderTarget)); ASSERT(!mImageArray[level]->isDirty()); - return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget); + return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type, + renderTarget); } else { - return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0); } } -gl::Error TextureD3D_2D::setCompressedImage(GLenum target, +gl::Error TextureD3D_2D::setCompressedImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -785,84 +916,120 @@ gl::Error TextureD3D_2D::setCompressedImage(GLenum target, 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); + ANGLE_TRY(redefineImage(context, level, internalFormat, size, false)); - return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0); + return setCompressedImageImpl(context, 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) +gl::Error TextureD3D_2D::setCompressedSubImage(const gl::Context *context, + 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)); - gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); - if (error.isError()) - { - return error; - } + ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0)); - return commitRegion(index, area); + return commitRegion(context, index, area); } -gl::Error TextureD3D_2D::copyImage(GLenum target, +gl::Error TextureD3D_2D::copyImage(const gl::Context *context, + GLenum target, size_t imageLevel, - const gl::Rectangle &sourceArea, + const gl::Rectangle &origSourceArea, 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); + GLint level = static_cast<GLint>(imageLevel); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); + gl::Extents sourceExtents(origSourceArea.width, origSourceArea.height, 1); + ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, sourceExtents, + false)); + + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + + // Does the read area extend beyond the framebuffer? + bool outside = origSourceArea.x < 0 || origSourceArea.y < 0 || + origSourceArea.x + origSourceArea.width > fbSize.width || + origSourceArea.y + origSourceArea.height > fbSize.height; + + // In WebGL mode we need to zero the texture outside the framebuffer. + // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise + // zero it explicitly. + // TODO(fjhenigman): When robust resource is fully implemented look into making it a + // prerequisite for WebGL and deleting this code. + if (outside && + (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled())) + { + angle::MemoryBuffer *zero; + ANGLE_TRY(context->getZeroFilledBuffer( + origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero)); + gl::PixelUnpackState unpack; + unpack.alignment = 1; + ANGLE_TRY(setImage(context, target, imageLevel, internalFormat, sourceExtents, + internalFormatInfo.format, internalFormatInfo.type, unpack, + zero->data())); + } + + gl::Rectangle sourceArea; + if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &sourceArea)) + { + // Empty source area, nothing to do. + return gl::NoError(); + } gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Offset destOffset(0, 0, 0); + gl::Offset destOffset(sourceArea.x - origSourceArea.x, sourceArea.y - origSourceArea.y, 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) { - gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source)); mDirtyImages = true; } else { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - mImageArray[level]->markClean(); + ANGLE_TRY(ensureRenderTarget(context)); if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level)) { - error = mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, mTexStorage, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, level)); + ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea, internalFormat, + destOffset, mTexStorage, level)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2D::copySubImage(GLenum target, +gl::Error TextureD3D_2D::copySubImage(const gl::Context *context, + GLenum target, size_t imageLevel, - const gl::Offset &destOffset, - const gl::Rectangle &sourceArea, + const gl::Offset &origDestOffset, + const gl::Rectangle &origSourceArea, const gl::Framebuffer *source) { - ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0); + ASSERT(target == GL_TEXTURE_2D && origDestOffset.z == 0); + + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + gl::Rectangle sourceArea; + if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &sourceArea)) + { + return gl::NoError(); + } + const gl::Offset destOffset(origDestOffset.x + sourceArea.x - origSourceArea.x, + origDestOffset.y + sourceArea.y - origSourceArea.y, 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) @@ -874,44 +1041,162 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, // so we should use the non-rendering copy path. if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); - if (error.isError()) + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget(context)); + + if (isValidLevel(level)) { - return error; + ANGLE_TRY(updateStorageLevel(context, level)); + ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea, + gl::GetUnsizedFormat(getBaseLevelInternalFormat()), + destOffset, mTexStorage, level)); } + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::copyTexture(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + GLenum type, + size_t sourceLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + ASSERT(target == GL_TEXTURE_2D); + + GLenum sourceTarget = source->getTarget(); + + GLint destLevel = static_cast<GLint>(level); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); + gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), + static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); + ANGLE_TRY( + redefineImage(context, destLevel, internalFormatInfo.sizedInternalFormat, size, false)); + + gl::Rectangle sourceRect(0, 0, size.width, size.height); + gl::Offset destOffset(0, 0, 0); + + if (!isSRGB(destLevel) && canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel))) + { + ANGLE_TRY(ensureRenderTarget(context)); + ASSERT(isValidLevel(destLevel)); + ANGLE_TRY(updateStorageLevel(context, destLevel)); + + ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel), + sourceRect, internalFormatInfo.format, destOffset, + mTexStorage, target, destLevel, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + } + else + { + gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel)); + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ImageD3D *sourceImage = nullptr; + ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage)); + + gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel)); + ImageD3D *destImage = nullptr; + ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage)); + + ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); mDirtyImages = true; + + gl::Box destRegion(destOffset, size); + ANGLE_TRY(commitRegion(context, destImageIndex, destRegion)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_2D::copySubTexture(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + size_t sourceLevel, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + ASSERT(target == GL_TEXTURE_2D); + + GLint destLevel = static_cast<GLint>(level); + + if (!isSRGB(destLevel) && canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel))) + { + ANGLE_TRY(ensureRenderTarget(context)); + ASSERT(isValidLevel(destLevel)); + ANGLE_TRY(updateStorageLevel(context, destLevel)); + + ANGLE_TRY(mRenderer->copyTexture( + context, source, static_cast<GLint>(sourceLevel), sourceArea, + gl::GetUnsizedFormat(getInternalFormat(destLevel)), destOffset, mTexStorage, target, + destLevel, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); } else { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel)); + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ImageD3D *sourceImage = nullptr; + ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage)); - if (isValidLevel(level)) - { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } + gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel)); + ImageD3D *destImage = nullptr; + ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage)); - error = mRenderer->copyImage2D(source, sourceArea, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - destOffset, mTexStorage, level); - if (error.isError()) - { - return error; - } - } + ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + + mDirtyImages = true; + + gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceArea.width, sourceArea.height, 1); + ANGLE_TRY(commitRegion(context, destImageIndex, destRegion)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error TextureD3D_2D::copyCompressedTexture(const gl::Context *context, + const gl::Texture *source) +{ + GLenum sourceTarget = source->getTarget(); + GLint sourceLevel = 0; + + GLint destLevel = 0; + + GLenum sizedInternalFormat = + source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat; + gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), + static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); + ANGLE_TRY(redefineImage(context, destLevel, sizedInternalFormat, size, false)); + + ANGLE_TRY(initializeStorage(context, false)); + ASSERT(mTexStorage); + + ANGLE_TRY( + mRenderer->copyCompressedTexture(context, source, sourceLevel, mTexStorage, destLevel)); + + return gl::NoError(); } -gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +gl::Error TextureD3D_2D::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) { ASSERT(GL_TEXTURE_2D && size.depth == 1); @@ -920,49 +1205,38 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level), 1); - redefineImage(level, internalFormat, levelSize, true); + ANGLE_TRY(redefineImage(context, 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); + ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true)); } // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2D( - internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false); + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TexStoragePointer storage(context); + storage.reset(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; - } - - error = updateStorage(); + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); mImmutable = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_2D::bindTexImage(egl::Surface *surface) +gl::Error TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surface *surface) { GLenum internalformat = surface->getConfig()->renderTargetFormat; gl::Extents size(surface->getWidth(), surface->getHeight(), 1); - redefineImage(0, internalformat, size, true); + ANGLE_TRY(redefineImage(context, 0, internalformat, size, true)); - if (mTexStorage) - { - SafeDelete(mTexStorage); - } + ANGLE_TRY(releaseTexStorage(context)); SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); ASSERT(surfaceD3D); @@ -970,78 +1244,84 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain()); mEGLImageTarget = false; - mDirtyImages = true; + mDirtyImages = false; + mImageArray[0]->markClean(); + + return gl::NoError(); } -void TextureD3D_2D::releaseTexImage() +gl::Error TextureD3D_2D::releaseTexImage(const gl::Context *context) { if (mTexStorage) { - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); } for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true); + ANGLE_TRY(redefineImage(context, i, GL_NONE, gl::Extents(0, 0, 1), true)); } + + return gl::NoError(); } -gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image) +gl::Error TextureD3D_2D::setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) { EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image); // Set the properties of the base mip level from the EGL image - GLenum internalformat = image->getInternalFormat(); + const auto &format = image->getFormat(); gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1); - redefineImage(0, internalformat, size, true); + ANGLE_TRY(redefineImage(context, 0, format.info->sizedInternalFormat, size, true)); // Clear all other images. - for (size_t level = 1; level < ArraySize(mImageArray); level++) + for (size_t level = 1; level < mImageArray.size(); level++) { - redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true); + ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true)); } - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); mImageArray[0]->markClean(); - mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d); + // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error. + RenderTargetD3D *renderTargetD3D = nullptr; + ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D)); + + mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D); mEGLImageTarget = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_2D::initMipmapsImages() +gl::Error TextureD3D_2D::initMipmapImages(const gl::Context *context) { - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) + 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(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1), - 1); + gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1), + std::max(getLevelZeroHeight() >> level, 1), 1); - redefineImage(level, getBaseLevelInternalFormat(), levelSize, false); + ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false)); } + return gl::NoError(); } -gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureD3D_2D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureRenderTarget(context)); + ANGLE_TRY(updateStorageLevel(context, index.mipIndex)); - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } - - return mTexStorage->getRenderTarget(index, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } bool TextureD3D_2D::isValidLevel(int level) const @@ -1056,10 +1336,8 @@ bool TextureD3D_2D::isLevelComplete(int level) const return true; } - const ImageD3D *baseImage = getBaseLevelImage(); - - GLsizei width = baseImage->getWidth(); - GLsizei height = baseImage->getHeight(); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); if (width <= 0 || height <= 0) { @@ -1067,15 +1345,16 @@ bool TextureD3D_2D::isLevelComplete(int level) const } // The base image level is complete if the width and height are positive - if (level == 0) + if (level == static_cast<int>(getBaseLevel())) { return true; } - ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ImageD3D *image = mImageArray[level]; + ASSERT(level >= 0 && level <= static_cast<int>(mImageArray.size()) && + mImageArray[level] != nullptr); + ImageD3D *image = mImageArray[level].get(); - if (image->getInternalFormat() != baseImage->getInternalFormat()) + if (image->getInternalFormat() != getBaseLevelInternalFormat()) { return false; } @@ -1099,52 +1378,41 @@ bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const } // Constructs a native texture resource from the texture images -gl::Error TextureD3D_2D::initializeStorage(bool renderTarget) +gl::Error TextureD3D_2D::initializeStorage(const gl::Context *context, 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); + return gl::NoError(); } // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) + if (!isLevelComplete(getBaseLevel())) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } + TexStoragePointer storage(context); + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); ASSERT(mTexStorage); // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const { - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); GLenum internalFormat = getBaseLevelInternalFormat(); ASSERT(width > 0 && height > 0); @@ -1165,84 +1433,83 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage } // TODO(geofflang): Determine if the texture creation succeeded - *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly); + outStorage->reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, + levels, hintLevelZeroOnly)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_2D::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) { if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) { for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) { - gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY( + mImageArray[level]->setManagedSurface2D(context, newCompleteTexStorage, level)); } } - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); mTexStorage = newCompleteTexStorage; mDirtyImages = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2D::updateStorage() +gl::Error TextureD3D_2D::updateStorage(const gl::Context *context) { - ASSERT(mTexStorage != NULL); + if (!mDirtyImages) + { + return gl::NoError(); + } + + ASSERT(mTexStorage != nullptr); GLint storageLevels = mTexStorage->getLevelCount(); for (int level = 0; level < storageLevels; level++) { if (mImageArray[level]->isDirty() && isLevelComplete(level)) { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, level)); } } - return gl::Error(GL_NO_ERROR); + mDirtyImages = false; + return gl::NoError(); } -gl::Error TextureD3D_2D::updateStorageLevel(int level) +gl::Error TextureD3D_2D::updateStorageLevel(const gl::Context *context, int level) { - ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(level <= static_cast<int>(mImageArray.size()) && mImageArray[level] != nullptr); 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); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(commitRegion(context, index, region)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_2D::redefineImage(size_t level, - GLenum internalformat, - const gl::Extents &size, - bool forceRelease) +gl::Error TextureD3D_2D::redefineImage(const gl::Context *context, + 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, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + 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); + mDirtyImages = mDirtyImages || mImageArray[level]->isDirty(); if (mTexStorage) { @@ -1252,27 +1519,23 @@ void TextureD3D_2D::redefineImage(size_t level, // while orphaning if (level != 0 && mEGLImageTarget) { - // TODO(jmadill): Don't discard error. - mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage); + ANGLE_TRY(mImageArray[0]->copyFromTexStorage(context, gl::ImageIndex::Make2D(0), + mTexStorage)); } - if ((level >= storageLevels && storageLevels != 0) || - size.width != storageWidth || + if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth || size.height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage + internalformat != storageFormat) // Discard mismatched storage { - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - SafeDelete(mTexStorage); - mDirtyImages = true; + ANGLE_TRY(releaseTexStorage(context)); + markAllImagesDirty(); } } // Can't be an EGL image target after being redefined mEGLImageTarget = false; + + return gl::NoError(); } gl::ImageIndexIterator TextureD3D_2D::imageIterator() const @@ -1292,46 +1555,58 @@ bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); } -TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer) - : TextureD3D(renderer) +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 (auto &face : mImageArray) { - for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + for (auto &image : face) { - mImageArray[i][j] = renderer->createImage(); + image.reset(renderer->createImage()); } } } -TextureD3D_Cube::~TextureD3D_Cube() +gl::Error TextureD3D_Cube::onDestroy(const gl::Context *context) { - // 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++) + // 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 (auto &face : mImageArray) { - for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + for (auto &image : face) { - SafeDelete(mImageArray[i][j]); + image.reset(); } } + return TextureD3D::onDestroy(context); +} - SafeDelete(mTexStorage); +TextureD3D_Cube::~TextureD3D_Cube() +{ } 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]; + return mImageArray[layer][level].get(); } 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]; + return mImageArray[index.layerIndex][index.mipIndex].get(); } GLsizei TextureD3D_Cube::getLayerCount(int level) const @@ -1350,128 +1625,191 @@ GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const { - return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; + return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; } -gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image) +bool TextureD3D_Cube::isSRGB(GLint level, GLint layer) const +{ + return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).colorEncoding == GL_SRGB; +} + +gl::Error TextureD3D_Cube::setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -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) +gl::Error TextureD3D_Cube::setImage(const gl::Context *context, + 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); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); - redefineImage(index.layerIndex, static_cast<GLint>(level), sizedInternalFormat, size); + ANGLE_TRY(redefineImage(context, index.layerIndex, static_cast<GLint>(level), + internalFormatInfo.sizedInternalFormat, size, false)); - return setImageImpl(index, type, unpack, pixels, 0); + return setImageImpl(context, 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) +gl::Error TextureD3D_Cube::setSubImage(const gl::Context *context, + 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); + return TextureD3D::subImage(context, 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) +gl::Error TextureD3D_Cube::setCompressedImage(const gl::Context *context, + 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); + ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), static_cast<GLint>(level), + internalFormat, size, false)); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); - return setCompressedImageImpl(index, unpack, pixels, 0); + return setCompressedImageImpl(context, 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) +gl::Error TextureD3D_Cube::setCompressedSubImage(const gl::Context *context, + 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)); - gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); - if (error.isError()) - { - return error; - } - - return commitRegion(index, area); + ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0)); + return commitRegion(context, index, area); } -gl::Error TextureD3D_Cube::copyImage(GLenum target, +gl::Error TextureD3D_Cube::copyImage(const gl::Context *context, + GLenum target, size_t imageLevel, - const gl::Rectangle &sourceArea, + const gl::Rectangle &origSourceArea, GLenum internalFormat, const gl::Framebuffer *source) { int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(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::Extents size(origSourceArea.width, origSourceArea.height, 1); + ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), level, + internalFormatInfo.sizedInternalFormat, size, false)); + + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + + // Does the read area extend beyond the framebuffer? + bool outside = origSourceArea.x < 0 || origSourceArea.y < 0 || + origSourceArea.x + origSourceArea.width > fbSize.width || + origSourceArea.y + origSourceArea.height > fbSize.height; + + // In WebGL mode we need to zero the texture outside the framebuffer. + // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise + // zero it explicitly. + // TODO(fjhenigman): When robust resource is fully implemented look into making it a + // prerequisite for WebGL and deleting this code. + if (outside && context->getExtensions().webglCompatibility && + !context->isRobustResourceInitEnabled()) + { + angle::MemoryBuffer *zero; + ANGLE_TRY(context->getZeroFilledBuffer( + origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero)); + gl::PixelUnpackState unpack; + unpack.alignment = 1; + ANGLE_TRY(setImage(context, target, imageLevel, internalFormat, size, + internalFormatInfo.format, internalFormatInfo.type, unpack, + zero->data())); + } + + gl::Rectangle sourceArea; + if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &sourceArea)) + { + // Empty source area, nothing to do. + return gl::NoError(); + } gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - gl::Offset destOffset(0, 0, 0); + gl::Offset destOffset(sourceArea.x - origSourceArea.x, sourceArea.y - origSourceArea.y, 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) { - gl::Error error = - mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset, + sourceArea, source)); mDirtyImages = true; } else { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - mImageArray[faceIndex][level]->markClean(); + ANGLE_TRY(ensureRenderTarget(context)); ASSERT(size.width == size.height); if (size.width > 0 && isValidFaceLevel(faceIndex, level)) { - error = mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, mTexStorage, target, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, level)); + ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea, internalFormat, + destOffset, mTexStorage, target, level)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_Cube::copySubImage(GLenum target, +gl::Error TextureD3D_Cube::copySubImage(const gl::Context *context, + GLenum target, size_t imageLevel, - const gl::Offset &destOffset, - const gl::Rectangle &sourceArea, + const gl::Offset &origDestOffset, + const gl::Rectangle &origSourceArea, const gl::Framebuffer *source) { + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + gl::Rectangle sourceArea; + if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &sourceArea)) + { + return gl::NoError(); + } + const gl::Offset destOffset(origDestOffset.x + sourceArea.x - origSourceArea.x, + origDestOffset.y + sourceArea.y - origSourceArea.y, 0); + int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); GLint level = static_cast<GLint>(imageLevel); @@ -1481,44 +1819,145 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target, // 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()) + ANGLE_TRY(mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset, + sourceArea, source)); + mDirtyImages = true; + } + else + { + ANGLE_TRY(ensureRenderTarget(context)); + if (isValidFaceLevel(faceIndex, level)) { - return error; + ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, level)); + ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea, + gl::GetUnsizedFormat(getBaseLevelInternalFormat()), + destOffset, mTexStorage, target, level)); } + } + + return gl::NoError(); +} + +gl::Error TextureD3D_Cube::copyTexture(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + GLenum type, + size_t sourceLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + ASSERT(gl::IsCubeMapTextureTarget(target)); + + GLenum sourceTarget = source->getTarget(); + + GLint destLevel = static_cast<GLint>(level); + int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); + gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), + static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); + ANGLE_TRY(redefineImage(context, faceIndex, destLevel, internalFormatInfo.sizedInternalFormat, + size, false)); + + gl::Rectangle sourceRect(0, 0, size.width, size.height); + gl::Offset destOffset(0, 0, 0); + + if (!isSRGB(destLevel, faceIndex) && + canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel))) + { + ANGLE_TRY(ensureRenderTarget(context)); + ASSERT(isValidFaceLevel(faceIndex, destLevel)); + ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel)); + + ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel), + sourceRect, internalFormatInfo.format, destOffset, + mTexStorage, target, destLevel, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + } + else + { + gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel)); + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ImageD3D *sourceImage = nullptr; + ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage)); + + gl::ImageIndex destImageIndex = + gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel)); + ImageD3D *destImage = nullptr; + ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage)); + + ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); mDirtyImages = true; + + gl::Box destRegion(destOffset, size); + ANGLE_TRY(commitRegion(context, destImageIndex, destRegion)); + } + + return gl::NoError(); +} + +gl::Error TextureD3D_Cube::copySubTexture(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + size_t sourceLevel, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) +{ + ASSERT(gl::IsCubeMapTextureTarget(target)); + + GLint destLevel = static_cast<GLint>(level); + int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target)); + + if (!isSRGB(destLevel, faceIndex) && + canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel))) + { + ANGLE_TRY(ensureRenderTarget(context)); + ASSERT(isValidFaceLevel(faceIndex, destLevel)); + ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel)); + + ANGLE_TRY(mRenderer->copyTexture( + context, source, static_cast<GLint>(sourceLevel), sourceArea, + gl::GetUnsizedFormat(getInternalFormat(destLevel, faceIndex)), destOffset, mTexStorage, + target, destLevel, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); } else { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel)); + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ImageD3D *sourceImage = nullptr; + ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage)); - if (isValidFaceLevel(faceIndex, level)) - { - error = updateStorageFaceLevel(faceIndex, level); - if (error.isError()) - { - return error; - } + gl::ImageIndex destImageIndex = + gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel)); + ImageD3D *destImage = nullptr; + ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage)); - error = mRenderer->copyImageCube(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - destOffset, mTexStorage, target, level); - if (error.isError()) - { - return error; - } - } + ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); + + mDirtyImages = true; + + gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceArea.width, sourceArea.height, 1); + ANGLE_TRY(commitRegion(context, destImageIndex, destRegion)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +gl::Error TextureD3D_Cube::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) { ASSERT(size.width == size.height); ASSERT(size.depth == 1); @@ -1541,28 +1980,20 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter } // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); - TextureStorage *storage = mRenderer->createTextureStorageCube( - internalFormat, renderTarget, size.width, static_cast<int>(levels), false); + TexStoragePointer storage(context); + storage.reset(mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, + static_cast<int>(levels), false)); - gl::Error error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - error = updateStorage(); + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); mImmutable = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -1579,7 +2010,7 @@ bool TextureD3D_Cube::isCubeComplete() const for (int faceIndex = 1; faceIndex < 6; faceIndex++) { - const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()]; if (faceBaseImage.getWidth() != baseWidth || faceBaseImage.getHeight() != baseHeight || @@ -1592,97 +2023,85 @@ bool TextureD3D_Cube::isCubeComplete() const return true; } -void TextureD3D_Cube::bindTexImage(egl::Surface *surface) +gl::Error TextureD3D_Cube::bindTexImage(const gl::Context *context, egl::Surface *surface) { UNREACHABLE(); + return gl::InternalError(); } -void TextureD3D_Cube::releaseTexImage() +gl::Error TextureD3D_Cube::releaseTexImage(const gl::Context *context) { UNREACHABLE(); + return gl::InternalError(); } - -void TextureD3D_Cube::initMipmapsImages() +gl::Error TextureD3D_Cube::initMipmapImages(const gl::Context *context) { - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); + 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 (int level = 1; level < levelCount; level++) + for (GLuint level = baseLevel + 1; level <= maxLevel; level++) { - int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); - redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), - gl::Extents(faceLevelSize, faceLevelSize, 1)); + int faceLevelSize = + (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1)); + ANGLE_TRY(redefineImage(context, faceIndex, level, + mImageArray[faceIndex][baseLevel]->getInternalFormat(), + gl::Extents(faceLevelSize, faceLevelSize, 1), false)); } } + return gl::NoError(); } -gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureD3D_Cube::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(gl::IsCubeMapTextureTarget(index.type)); // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - error = updateStorageFaceLevel(index.layerIndex, index.mipIndex); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureRenderTarget(context)); + ANGLE_TRY(updateStorageFaceLevel(context, index.layerIndex, index.mipIndex)); - return mTexStorage->getRenderTarget(index, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } -gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget) +gl::Error TextureD3D_Cube::initializeStorage(const gl::Context *context, 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); + return gl::NoError(); } // do not attempt to create storage for nonexistant data - if (!isFaceLevelComplete(0, 0)) + if (!isFaceLevelComplete(0, getBaseLevel())) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } + TexStoragePointer storage(context); + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); ASSERT(mTexStorage); // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const { - GLsizei size = getBaseLevelWidth(); + GLsizei size = getLevelZeroWidth(); ASSERT(size > 0); @@ -1705,12 +2124,14 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora } // TODO (geofflang): detect if storage creation succeeded - *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly); + outStorage->reset(mRenderer->createTextureStorageCube( + getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) { if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) { @@ -1718,25 +2139,27 @@ gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexS { for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) { - gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube( + context, newCompleteTexStorage, faceIndex, level)); } } } - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); mTexStorage = newCompleteTexStorage; mDirtyImages = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_Cube::updateStorage() +gl::Error TextureD3D_Cube::updateStorage(const gl::Context *context) { - ASSERT(mTexStorage != NULL); + if (!mDirtyImages) + { + return gl::NoError(); + } + + ASSERT(mTexStorage != nullptr); GLint storageLevels = mTexStorage->getLevelCount(); for (int face = 0; face < 6; face++) { @@ -1744,16 +2167,13 @@ gl::Error TextureD3D_Cube::updateStorage() { if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) { - gl::Error error = updateStorageFaceLevel(face, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageFaceLevel(context, face, level)); } } } - return gl::Error(GL_NO_ERROR); + mDirtyImages = false; + return gl::NoError(); } bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const @@ -1763,16 +2183,21 @@ bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const { - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return false; + } + ASSERT(level >= 0 && faceIndex < 6 && level < static_cast<int>(mImageArray[faceIndex].size()) && + mImageArray[faceIndex][level] != nullptr); if (isImmutable()) { return true; } - int baseSize = getBaseLevelWidth(); + int levelZeroSize = getLevelZeroWidth(); - if (baseSize <= 0) + if (levelZeroSize <= 0) { return false; } @@ -1786,14 +2211,14 @@ bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const } // Check that non-zero levels are consistent with the base level. - const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level].get(); if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) { return false; } - if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) + if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level)) { return false; } @@ -1806,57 +2231,55 @@ bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const return isFaceLevelComplete(index.layerIndex, index.mipIndex); } -gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +gl::Error TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context, + int faceIndex, + int level) { - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); - ImageD3D *image = mImageArray[faceIndex][level]; + ASSERT(level >= 0 && faceIndex < 6 && level < static_cast<int>(mImageArray[faceIndex].size()) && + mImageArray[faceIndex][level] != nullptr); + ImageD3D *image = mImageArray[faceIndex][level].get(); 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); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(commitRegion(context, index, region)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size) +gl::Error TextureD3D_Cube::redefineImage(const gl::Context *context, + int faceIndex, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + 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); + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, + forceRelease); + mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty(); if (mTexStorage) { const int storageLevels = mTexStorage->getLevelCount(); - if ((level >= storageLevels && storageLevels != 0) || - size.width != storageWidth || + if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth || size.height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage + internalformat != storageFormat) // Discard mismatched storage { - for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) - { - for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++) - { - mImageArray[dirtyFace][dirtyLevel]->markDirty(); - } - } - - SafeDelete(mTexStorage); - - mDirtyImages = true; + markAllImagesDirty(); + ANGLE_TRY(releaseTexStorage(context)); } } + + return gl::NoError(); } gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const @@ -1876,33 +2299,48 @@ bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); } -TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer) - : TextureD3D(renderer) +void TextureD3D_Cube::markAllImagesDirty() { - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) { - mImageArray[i] = renderer->createImage(); + for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++) + { + mImageArray[dirtyFace][dirtyLevel]->markDirty(); + } } + mDirtyImages = true; } -TextureD3D_3D::~TextureD3D_3D() +TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer) + : TextureD3D(state, renderer) { - // 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]; + mImageArray[i].reset(renderer->createImage()); } +} - SafeDelete(mTexStorage); +gl::Error TextureD3D_3D::onDestroy(const gl::Context *context) +{ + // 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 (auto &image : mImageArray) + { + image.reset(); + } + return TextureD3D::onDestroy(context); +} + +TextureD3D_3D::~TextureD3D_3D() +{ } ImageD3D *TextureD3D_3D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(layer == 0); - return mImageArray[level]; + return mImageArray[level].get(); } ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const @@ -1910,7 +2348,7 @@ 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]; + return mImageArray[index.mipIndex].get(); } GLsizei TextureD3D_3D::getLayerCount(int level) const @@ -1953,16 +2391,19 @@ GLenum TextureD3D_3D::getInternalFormat(GLint level) const bool TextureD3D_3D::isDepth(GLint level) const { - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; + return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image) +gl::Error TextureD3D_3D::setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error TextureD3D_3D::setImage(GLenum target, +gl::Error TextureD3D_3D::setImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -1972,33 +2413,29 @@ gl::Error TextureD3D_3D::setImage(GLenum target, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); GLint level = static_cast<GLint>(imageLevel); - redefineImage(level, sizedInternalFormat, size); + ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, size, false)); 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()) + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && !size.empty() && + isLevelComplete(level)) { // Will try to create RT storage if it does not exist - RenderTargetD3D *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget)); gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea, + internalFormatInfo.sizedInternalFormat, type, destRenderTarget)); // Ensure we don't overwrite our newly initialized data mImageArray[level]->markClean(); @@ -2008,17 +2445,14 @@ gl::Error TextureD3D_3D::setImage(GLenum target, if (!fastUnpacked) { - gl::Error error = setImageImpl(index, type, unpack, pixels, 0); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_3D::setSubImage(GLenum target, +gl::Error TextureD3D_3D::setSubImage(const gl::Context *context, + GLenum target, size_t imageLevel, const gl::Box &area, GLenum format, @@ -2032,26 +2466,25 @@ gl::Error TextureD3D_3D::setSubImage(GLenum target, 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))) + gl::Buffer *unpackBuffer = + context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); + if (isFastUnpackable(unpackBuffer, getInternalFormat(level)) && isLevelComplete(level)) { - RenderTargetD3D *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget)); ASSERT(!mImageArray[level]->isDirty()); - return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget); + return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type, + destRenderTarget); } else { - return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0); } } -gl::Error TextureD3D_3D::setCompressedImage(GLenum target, +gl::Error TextureD3D_3D::setCompressedImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -2063,35 +2496,41 @@ gl::Error TextureD3D_3D::setCompressedImage(GLenum target, 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); + ANGLE_TRY(redefineImage(context, level, internalFormat, size, false)); gl::ImageIndex index = gl::ImageIndex::Make3D(level); - return setCompressedImageImpl(index, unpack, pixels, 0); + return setCompressedImageImpl(context, 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) +gl::Error TextureD3D_3D::setCompressedSubImage(const gl::Context *context, + 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)); - gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); - if (error.isError()) - { - return error; - } - - return commitRegion(index, area); + ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0)); + return commitRegion(context, index, area); } -gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, +gl::Error TextureD3D_3D::copyImage(const gl::Context *context, + 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."); + return gl::InternalError() << "Copying 3D textures is unimplemented."; } -gl::Error TextureD3D_3D::copySubImage(GLenum target, +gl::Error TextureD3D_3D::copySubImage(const gl::Context *context, + GLenum target, size_t imageLevel, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, @@ -2099,49 +2538,47 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target, { ASSERT(target == GL_TEXTURE_3D); - GLint level = static_cast<GLint>(imageLevel); - gl::ImageIndex index = gl::ImageIndex::Make3D(level); + GLint level = static_cast<GLint>(imageLevel); - if (canCreateRenderTargetForImage(index)) + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + gl::Rectangle clippedSourceArea; + if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &clippedSourceArea)) { - gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; + return gl::NoError(); } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x, + destOffset.y + clippedSourceArea.y - sourceArea.y, + destOffset.z); - if (isValidLevel(level)) - { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } + // Currently, copying directly to the storage is not possible because it's not possible to + // create an SRV from a single layer of a 3D texture. Instead, make sure the image is up to + // date before the copy and then copy back to the storage afterwards if needed. + // TODO: Investigate 3D blits in D3D11. - error = mRenderer->copyImage3D(source, sourceArea, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - destOffset, mTexStorage, level); - if (error.isError()) - { - return error; - } - } + bool syncTexStorage = mTexStorage && isLevelComplete(level); + if (syncTexStorage) + { + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + ANGLE_TRY(mImageArray[level]->copyFromTexStorage(context, index, mTexStorage)); } + ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, clippedDestOffset, clippedSourceArea, + source)); + mDirtyImages = true; - return gl::Error(GL_NO_ERROR); + if (syncTexStorage) + { + ANGLE_TRY(updateStorageLevel(context, level)); + } + + return gl::NoError(); } -gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +gl::Error TextureD3D_3D::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) { ASSERT(target == GL_TEXTURE_3D); @@ -2159,130 +2596,106 @@ gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum interna } // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = - mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, - size.depth, static_cast<int>(levels)); + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TexStoragePointer storage(context); + storage.reset(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(setCompleteTexStorage(context, storage.get())); + storage.release(); - error = updateStorage(); - - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); mImmutable = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_3D::bindTexImage(egl::Surface *surface) +gl::Error TextureD3D_3D::bindTexImage(const gl::Context *context, egl::Surface *surface) { UNREACHABLE(); + return gl::InternalError(); } -void TextureD3D_3D::releaseTexImage() +gl::Error TextureD3D_3D::releaseTexImage(const gl::Context *context) { UNREACHABLE(); + return gl::InternalError(); } - -void TextureD3D_3D::initMipmapsImages() +gl::Error TextureD3D_3D::initMipmapImages(const gl::Context *context) { - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) + 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(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1), - std::max(getBaseLevelDepth() >> level, 1)); - redefineImage(level, getBaseLevelInternalFormat(), levelSize); + gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1), + std::max(getLevelZeroHeight() >> level, 1), + std::max(getLevelZeroDepth() >> level, 1)); + ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false)); } + + return gl::NoError(); } -gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureD3D_3D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureRenderTarget(context)); if (index.hasLayer()) { - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); } else { - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, index.mipIndex)); } - return mTexStorage->getRenderTarget(index, outRT); + return mTexStorage->getRenderTarget(context, index, outRT); } -gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) +gl::Error TextureD3D_3D::initializeStorage(const gl::Context *context, 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); + return gl::NoError(); } // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) + if (!isLevelComplete(getBaseLevel())) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } + TexStoragePointer storage(context); + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); ASSERT(mTexStorage); // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const { - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLevelZeroDepth(); GLenum internalFormat = getBaseLevelInternalFormat(); ASSERT(width > 0 && height > 0 && depth > 0); @@ -2291,40 +2704,44 @@ gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage 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); + outStorage->reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, + depth, levels)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_3D::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) { - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); mTexStorage = newCompleteTexStorage; mDirtyImages = true; // We do not support managed 3D storage, as that is D3D9/ES2-only ASSERT(!mTexStorage->isManaged()); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_3D::updateStorage() +gl::Error TextureD3D_3D::updateStorage(const gl::Context *context) { - ASSERT(mTexStorage != NULL); + if (!mDirtyImages) + { + return gl::NoError(); + } + + ASSERT(mTexStorage != nullptr); GLint storageLevels = mTexStorage->getLevelCount(); for (int level = 0; level < storageLevels; level++) { if (mImageArray[level]->isDirty() && isLevelComplete(level)) { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, level)); } } - return gl::Error(GL_NO_ERROR); + mDirtyImages = false; + return gl::NoError(); } bool TextureD3D_3D::isValidLevel(int level) const @@ -2334,28 +2751,29 @@ bool TextureD3D_3D::isValidLevel(int level) const bool TextureD3D_3D::isLevelComplete(int level) const { - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) && + mImageArray[level] != nullptr); if (isImmutable()) { return true; } - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLevelZeroDepth(); if (width <= 0 || height <= 0 || depth <= 0) { return false; } - if (level == 0) + if (level == static_cast<int>(getBaseLevel())) { return true; } - ImageD3D *levelImage = mImageArray[level]; + ImageD3D *levelImage = mImageArray[level].get(); if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) { @@ -2385,54 +2803,51 @@ bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const return isLevelComplete(index.mipIndex); } -gl::Error TextureD3D_3D::updateStorageLevel(int level) +gl::Error TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level) { - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) && + mImageArray[level] != nullptr); 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)); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(commitRegion(context, index, region)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +gl::Error TextureD3D_3D::redefineImage(const gl::Context *context, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = std::max(1, getBaseLevelDepth() >> level); + 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); + mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, forceRelease); + mDirtyImages = mDirtyImages || mImageArray[level]->isDirty(); 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 + if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth || + size.height != storageHeight || size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage { - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - SafeDelete(mTexStorage); - mDirtyImages = true; + markAllImagesDirty(); + ANGLE_TRY(releaseTexStorage(context)); } } + + return gl::NoError(); } gl::ImageIndexIterator TextureD3D_3D::imageIterator() const @@ -2453,23 +2868,42 @@ bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); } -TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer) - : TextureD3D(renderer) +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; + mImageArray[level] = nullptr; } } -TextureD3D_2DArray::~TextureD3D_2DArray() +gl::Error TextureD3D_2DArray::onDestroy(const gl::Context *context) { - // 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. + // 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); + return TextureD3D::onDestroy(context); +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ } ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const @@ -2477,16 +2911,17 @@ 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); + return (mImageArray[level] ? mImageArray[level][layer] : nullptr); } ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const { ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(index.layerIndex != gl::ImageIndex::ENTIRE_LEVEL); 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); + return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : nullptr); } GLsizei TextureD3D_2DArray::getLayerCount(int level) const @@ -2512,16 +2947,19 @@ GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const bool TextureD3D_2DArray::isDepth(GLint level) const { - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; + return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image) +gl::Error TextureD3D_2DArray::setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error TextureD3D_2DArray::setImage(GLenum target, +gl::Error TextureD3D_2DArray::setImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -2532,30 +2970,28 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, { ASSERT(target == GL_TEXTURE_2D_ARRAY); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type); GLint level = static_cast<GLint>(imageLevel); - redefineImage(level, sizedInternalFormat, size); + ANGLE_TRY(redefineImage(context, level, formatInfo.sizedInternalFormat, size, false)); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch( - type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, 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); - gl::Error error = setImageImpl(index, type, unpack, pixels, layerOffset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, layerOffset)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::setSubImage(GLenum target, +gl::Error TextureD3D_2DArray::setSubImage(const gl::Context *context, + GLenum target, size_t imageLevel, const gl::Box &area, GLenum format, @@ -2565,9 +3001,12 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target, { ASSERT(target == GL_TEXTURE_2D_ARRAY); GLint level = static_cast<GLint>(imageLevel); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch( - type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); + const gl::InternalFormat &formatInfo = + gl::GetInternalFormatInfo(getInternalFormat(level), type); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, + unpack.rowLength, unpack.imageHeight), + inputDepthPitch); for (int i = 0; i < area.depth; i++) { @@ -2577,17 +3016,15 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target, gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Error error = TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(TextureD3D::subImage(context, index, layerArea, format, type, unpack, pixels, + layerOffset)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, +gl::Error TextureD3D_2DArray::setCompressedImage(const gl::Context *context, + GLenum target, size_t imageLevel, GLenum internalFormat, const gl::Extents &size, @@ -2599,35 +3036,41 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, 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); + ANGLE_TRY(redefineImage(context, level, internalFormat, size, false)); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - GLsizei inputDepthPitch = - formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, 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); - gl::Error error = setCompressedImageImpl(index, unpack, pixels, layerOffset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setCompressedImageImpl(context, index, unpack, pixels, layerOffset)); } - return gl::Error(GL_NO_ERROR); + 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) +gl::Error TextureD3D_2DArray::setCompressedSubImage(const gl::Context *context, + 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 = - formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0), + inputDepthPitch); for (int i = 0; i < area.depth; i++) { @@ -2637,30 +3080,27 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer); - gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset); - if (error.isError()) - { - return error; - } - - error = commitRegion(index, layerArea); - if (error.isError()) - { - return error; - } + ANGLE_TRY(TextureD3D::subImageCompressed(context, index, layerArea, format, unpack, pixels, + layerOffset)); + ANGLE_TRY(commitRegion(context, index, layerArea)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, +gl::Error TextureD3D_2DArray::copyImage(const gl::Context *context, + 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."); + return gl::InternalError() << "Copying 2D array textures is unimplemented."; } -gl::Error TextureD3D_2DArray::copySubImage(GLenum target, +gl::Error TextureD3D_2DArray::copySubImage(const gl::Context *context, + GLenum target, size_t imageLevel, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, @@ -2671,46 +3111,45 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level = static_cast<GLint>(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); - if (canCreateRenderTargetForImage(index)) + gl::Extents fbSize = source->getReadColorbuffer()->getSize(); + gl::Rectangle clippedSourceArea; + if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), + &clippedSourceArea)) { - gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0); - gl::Error error = mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, - sourceArea, source); - if (error.isError()) - { - return error; - } + return gl::NoError(); + } + const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x, + destOffset.y + clippedSourceArea.y - sourceArea.y, + destOffset.z); + if (!canCreateRenderTargetForImage(index)) + { + gl::Offset destLayerOffset(clippedDestOffset.x, clippedDestOffset.y, 0); + ANGLE_TRY(mImageArray[level][clippedDestOffset.z]->copyFromFramebuffer( + context, destLayerOffset, clippedSourceArea, source)); mDirtyImages = true; } else { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureRenderTarget(context)); if (isValidLevel(level)) { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - - error = mRenderer->copyImage2DArray(source, sourceArea, gl::GetInternalFormatInfo(getInternalFormat(0)).format, - destOffset, mTexStorage, level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, level)); + ANGLE_TRY( + mRenderer->copyImage2DArray(context, source, clippedSourceArea, + gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())), + clippedDestOffset, mTexStorage, level)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +gl::Error TextureD3D_2DArray::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -2738,124 +3177,103 @@ gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum in } // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = - mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, - size.height, size.depth, static_cast<int>(levels)); + bool renderTarget = IsRenderTargetUsage(mState.getUsage()); + TexStoragePointer storage(context); + storage.reset(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(setCompleteTexStorage(context, storage.get())); + storage.release(); - error = updateStorage(); - - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); mImmutable = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) +gl::Error TextureD3D_2DArray::bindTexImage(const gl::Context *context, egl::Surface *surface) { UNREACHABLE(); + return gl::InternalError(); } -void TextureD3D_2DArray::releaseTexImage() +gl::Error TextureD3D_2DArray::releaseTexImage(const gl::Context *context) { UNREACHABLE(); + return gl::InternalError(); } - -void TextureD3D_2DArray::initMipmapsImages() +gl::Error TextureD3D_2DArray::initMipmapImages(const gl::Context *context) { - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - int baseDepth = getLayerCount(0); + 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 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) + // 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); + ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false)); } + + return gl::NoError(); } -gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureD3D_2DArray::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } - - return mTexStorage->getRenderTarget(index, outRT); + ANGLE_TRY(ensureRenderTarget(context)); + ANGLE_TRY(updateStorageLevel(context, index.mipIndex)); + return mTexStorage->getRenderTarget(context, index, outRT); } -gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) +gl::Error TextureD3D_2DArray::initializeStorage(const gl::Context *context, 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); + return gl::NoError(); } // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) + if (!isLevelComplete(getBaseLevel())) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } + TexStoragePointer storage(context); + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); ASSERT(mTexStorage); // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorage(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const { - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayerCount(0); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); + GLsizei depth = getLayerCount(getBaseLevel()); GLenum internalFormat = getBaseLevelInternalFormat(); ASSERT(width > 0 && height > 0 && depth > 0); @@ -2864,40 +3282,44 @@ gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureSt GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); // TODO(geofflang): Verify storage creation succeeds - *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); + outStorage->reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, + height, depth, levels)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) { - SafeDelete(mTexStorage); + ANGLE_TRY(releaseTexStorage(context)); mTexStorage = newCompleteTexStorage; mDirtyImages = true; // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only ASSERT(!mTexStorage->isManaged()); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureD3D_2DArray::updateStorage() +gl::Error TextureD3D_2DArray::updateStorage(const gl::Context *context) { - ASSERT(mTexStorage != NULL); + if (!mDirtyImages) + { + return gl::NoError(); + } + + ASSERT(mTexStorage != nullptr); GLint storageLevels = mTexStorage->getLevelCount(); for (int level = 0; level < storageLevels; level++) { if (isLevelComplete(level)) { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } + ANGLE_TRY(updateStorageLevel(context, level)); } } - return gl::Error(GL_NO_ERROR); + mDirtyImages = false; + return gl::NoError(); } bool TextureD3D_2DArray::isValidLevel(int level) const @@ -2914,21 +3336,29 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const return true; } - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei layers = getLayerCount(0); + GLsizei width = getLevelZeroWidth(); + GLsizei height = getLevelZeroHeight(); - if (width <= 0 || height <= 0 || layers <= 0) + if (width <= 0 || height <= 0) { return false; } - if (level == 0) + // 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(0)) + if (getInternalFormat(level) != getInternalFormat(getBaseLevel())) { return false; } @@ -2956,27 +3386,23 @@ bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const return isLevelComplete(index.mipIndex); } -gl::Error TextureD3D_2DArray::updateStorageLevel(int level) +gl::Error TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level) { - ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(level >= 0 && level < static_cast<int>(ArraySize(mLayerCounts))); ASSERT(isLevelComplete(level)); for (int layer = 0; layer < mLayerCounts[level]; layer++) { - ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + ASSERT(mImageArray[level] != nullptr && mImageArray[level][layer] != nullptr); if (mImageArray[level][layer]->isDirty()) { gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(commitRegion(context, index, region)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void TextureD3D_2DArray::deleteImages() @@ -2988,18 +3414,26 @@ void TextureD3D_2DArray::deleteImages() delete mImageArray[level][layer]; } delete[] mImageArray[level]; - mImageArray[level] = NULL; + mImageArray[level] = nullptr; mLayerCounts[level] = 0; } } -void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +gl::Error TextureD3D_2DArray::redefineImage(const gl::Context *context, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = getLayerCount(0); - const GLenum storageFormat = getBaseLevelInternalFormat(); + 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]) @@ -3026,33 +3460,27 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const 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); + gl::Extents(size.width, size.height, 1), + forceRelease); + mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty(); } } 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 + if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth || + size.height != storageHeight || size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage { - for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) - { - for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++) - { - mImageArray[dirtyLevel][dirtyLayer]->markDirty(); - } - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; + markAllImagesDirty(); + ANGLE_TRY(releaseTexStorage(context)); } } + + return gl::NoError(); } gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const @@ -3083,4 +3511,464 @@ bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const 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() +{ +} + +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(const gl::Context *context, + 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::InternalError(); +} + +gl::Error TextureD3D_External::setSubImage(const gl::Context *context, + GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::setCompressedImage(const gl::Context *context, + 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::InternalError(); +} + +gl::Error TextureD3D_External::setCompressedSubImage(const gl::Context *context, + 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::InternalError(); +} + +gl::Error TextureD3D_External::copyImage(const gl::Context *context, + GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::copySubImage(const gl::Context *context, + GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::setImageExternal(const gl::Context *context, + GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + ASSERT(target == GL_TEXTURE_EXTERNAL_OES); + + ANGLE_TRY(releaseTexStorage(context)); + + // 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::NoError(); +} + +gl::Error TextureD3D_External::bindTexImage(const gl::Context *context, egl::Surface *surface) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::releaseTexImage(const gl::Context *context) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::setEGLImageTarget(const gl::Context *context, + 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(context, &renderTargetD3D)); + + ANGLE_TRY(releaseTexStorage(context)); + mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D); + + return gl::NoError(); +} + +gl::Error TextureD3D_External::initMipmapImages(const gl::Context *context) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_External::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const +{ + return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false; +} + +gl::Error TextureD3D_External::initializeStorage(const gl::Context *context, bool renderTarget) +{ + // Texture storage is created when an external image is bound + ASSERT(mTexStorage); + return gl::NoError(); +} + +gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const +{ + UNREACHABLE(); + return gl::NoError(); +} + +gl::Error TextureD3D_External::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) +{ + UNREACHABLE(); + return gl::NoError(); +} + +gl::Error TextureD3D_External::updateStorage(const gl::Context *context) +{ + // Texture storage does not need to be updated since it is already loaded with the latest + // external image + ASSERT(mTexStorage); + return gl::NoError(); +} + +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(); +} + +TextureD3D_2DMultisample::TextureD3D_2DMultisample(const gl::TextureState &state, + RendererD3D *renderer) + : TextureD3D(state, renderer) +{ +} + +TextureD3D_2DMultisample::~TextureD3D_2DMultisample() +{ +} + +ImageD3D *TextureD3D_2DMultisample::getImage(const gl::ImageIndex &index) const +{ + return nullptr; +} + +gl::Error TextureD3D_2DMultisample::setImage(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::setSubImage(const gl::Context *context, + GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::setCompressedImage(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::setCompressedSubImage(const gl::Context *context, + 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::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::copyImage(const gl::Context *context, + GLenum target, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::copySubImage(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::setStorageMultisample(const gl::Context *context, + GLenum target, + GLsizei samples, + GLint internalFormat, + const gl::Extents &size, + bool fixedSampleLocations) +{ + ASSERT(target == GL_TEXTURE_2D_MULTISAMPLE && size.depth == 1); + + TexStoragePointer storage(context); + storage.reset(mRenderer->createTextureStorage2DMultisample(internalFormat, size.width, + size.height, static_cast<int>(0), + samples, fixedSampleLocations)); + + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); + + ANGLE_TRY(updateStorage(context)); + + mImmutable = false; + + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::bindTexImage(const gl::Context *context, egl::Surface *surface) +{ + UNREACHABLE(); + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::releaseTexImage(const gl::Context *context) +{ + UNREACHABLE(); + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) +{ + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + // ensure the underlying texture is created + ANGLE_TRY(ensureRenderTarget(context)); + + return mTexStorage->getRenderTarget(context, index, outRT); +} + +gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const +{ + return gl::ImageIndexIterator::Make2DMultisample(); +} + +gl::ImageIndex TextureD3D_2DMultisample::getImageIndex(GLint mip, GLint layer) const +{ + return gl::ImageIndex::Make2DMultisample(); +} + +bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_2D_MULTISAMPLE && index.mipIndex == 0); +} + +GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const +{ + return 1; } + +void TextureD3D_2DMultisample::markAllImagesDirty() +{ +} + +gl::Error TextureD3D_2DMultisample::initializeStorage(const gl::Context *context, bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::NoError(); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage())); + + TexStoragePointer storage(context); + ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage)); + + ANGLE_TRY(setCompleteTexStorage(context, storage.get())); + storage.release(); + + ASSERT(mTexStorage); + + // flush image data to the storage + ANGLE_TRY(updateStorage(context)); + + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const +{ + outStorage->reset(mTexStorage); + + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) +{ + ANGLE_TRY(releaseTexStorage(context)); + mTexStorage = newCompleteTexStorage; + + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::updateStorage(const gl::Context *context) +{ + return gl::NoError(); +} + +gl::Error TextureD3D_2DMultisample::initMipmapImages(const gl::Context *context) +{ + UNIMPLEMENTED(); + return gl::NoError(); +} + +bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const +{ + return true; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h index 1d5faee703..eb206a6ccc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h @@ -9,9 +9,12 @@ #ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ #define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ -#include "libANGLE/renderer/TextureImpl.h" -#include "libANGLE/angletypes.h" +#include "common/Color.h" #include "libANGLE/Constants.h" +#include "libANGLE/Stream.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" namespace gl { @@ -26,29 +29,51 @@ class RendererD3D; class RenderTargetD3D; class TextureStorage; +template <typename T> +using TexLevelsArray = std::array<T, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS>; + class TextureD3D : public TextureImpl { public: - TextureD3D(RendererD3D *renderer); - virtual ~TextureD3D(); + TextureD3D(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D() override; + + gl::Error onDestroy(const gl::Context *context) override; - gl::Error getNativeTexture(TextureStorage **outStorage); + gl::Error getNativeTexture(const gl::Context *context, TextureStorage **outStorage); - virtual void setUsage(GLenum usage) { mUsage = usage; } 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; + gl::Error getImageAndSyncFromStorage(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D **outImage); + GLint getBaseLevelWidth() const; GLint getBaseLevelHeight() const; - GLint getBaseLevelDepth() const; GLenum getBaseLevelInternalFormat() const; + gl::Error setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error setStorageMultisample(const gl::Context *context, + GLenum target, + GLsizei samples, + GLint internalFormat, + const gl::Extents &size, + bool fixedSampleLocations) override; + bool isImmutable() const { return mImmutable; } - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + virtual gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) = 0; // Returns an iterator over all "Images" for this particular Texture. virtual gl::ImageIndexIterator imageIterator() const = 0; @@ -58,47 +83,91 @@ class TextureD3D : public TextureImpl virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; - gl::Error generateMipmaps(const gl::TextureState &textureState) override; + gl::Error setImageExternal(const gl::Context *context, + GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + gl::Error generateMipmap(const gl::Context *context) override; TextureStorage *getStorage(); ImageD3D *getBaseLevelImage() const; - gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + gl::Error getAttachmentRenderTarget(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) override; + gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override; + + void syncState(const gl::Texture::DirtyBits &dirtyBits) override; + + gl::Error initializeContents(const gl::Context *context, + const gl::ImageIndex &imageIndex) override; + protected: - gl::Error setImageImpl(const gl::ImageIndex &index, + gl::Error setImageImpl(const gl::Context *context, + 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, + gl::Error subImage(const gl::Context *context, + 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::Context *context, + 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); + gl::Error subImageCompressed(const gl::Context *context, + 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::Buffer *unpackBuffer, GLenum sizedInternalFormat); + gl::Error fastUnpackPixels(const gl::Context *context, + 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; - int mipLevels() const; - virtual void initMipmapsImages() = 0; + virtual gl::Error initMipmapImages(const gl::Context *context) = 0; bool isBaseImageZeroSize() const; virtual bool isImageComplete(const gl::ImageIndex &index) const = 0; bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const; - virtual gl::Error ensureRenderTarget(); + gl::Error ensureRenderTarget(const gl::Context *context); - 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); + virtual gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outTexStorage) const = 0; + virtual gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) = 0; + gl::Error commitRegion(const gl::Context *context, + const gl::ImageIndex &index, + const gl::Box ®ion); - RendererD3D *mRenderer; + gl::Error releaseTexStorage(const gl::Context *context); + + GLuint getBaseLevel() const { return mBaseLevel; }; - GLenum mUsage; + virtual void markAllImagesDirty() = 0; + + GLint getBaseLevelDepth() const; + + RendererD3D *mRenderer; bool mDirtyImages; @@ -106,154 +175,301 @@ class TextureD3D : public TextureImpl TextureStorage *mTexStorage; private: - virtual gl::Error initializeStorage(bool renderTarget) = 0; + virtual gl::Error initializeStorage(const gl::Context *context, bool renderTarget) = 0; - virtual gl::Error updateStorage() = 0; + virtual gl::Error updateStorage(const gl::Context *context) = 0; bool shouldUseSetData(const ImageD3D *image) const; - gl::Error generateMipmapsUsingImages(); + gl::Error generateMipmapUsingImages(const gl::Context *context, const GLuint maxLevel); + + GLuint mBaseLevel; }; class TextureD3D_2D : public TextureD3D { public: - TextureD3D_2D(RendererD3D *renderer); - virtual ~TextureD3D_2D(); + TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_2D() override; - virtual ImageD3D *getImage(int level, int layer) const; - virtual ImageD3D *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; + gl::Error onDestroy(const gl::Context *context) override; + + ImageD3D *getImage(int level, int layer) const; + ImageD3D *getImage(const gl::ImageIndex &index) const override; + GLsizei getLayerCount(int level) const override; GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; + bool isSRGB(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, + gl::Error setImage(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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, + gl::Error copySubImage(const gl::Context *context, + 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 copyTexture(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + GLenum type, + size_t sourceLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + gl::Error copySubTexture(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + size_t sourceLevel, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + gl::Error copyCompressedTexture(const gl::Context *context, const gl::Texture *source) override; + + gl::Error setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; + + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; + + gl::Error getRenderTarget(const gl::Context *context, + 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; - 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); + gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outTexStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) override; bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; + bool isImageComplete(const gl::ImageIndex &index) const override; - gl::Error updateStorageLevel(int level); + gl::Error updateStorageLevel(const gl::Context *context, int level); - void redefineImage(size_t level, - GLenum internalformat, - const gl::Extents &size, - bool forceRelease); + gl::Error redefineImage(const gl::Context *context, + size_t level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); bool mEGLImageTarget; - ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelsArray<std::unique_ptr<ImageD3D>> mImageArray; }; class TextureD3D_Cube : public TextureD3D { public: - TextureD3D_Cube(RendererD3D *renderer); - virtual ~TextureD3D_Cube(); + TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_Cube() override; - virtual ImageD3D *getImage(int level, int layer) const; - virtual ImageD3D *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; + gl::Error onDestroy(const gl::Context *context) override; - virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty() { mDirtyImages = false; } - virtual void setUsage(GLenum usage) { mUsage = usage; } + ImageD3D *getImage(int level, int layer) const; + ImageD3D *getImage(const gl::ImageIndex &index) const override; + GLsizei getLayerCount(int level) const override; GLenum getInternalFormat(GLint level, GLint layer) const; bool isDepth(GLint level, GLint layer) const; + bool isSRGB(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, + gl::Error setImage(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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, + gl::Error copySubImage(const gl::Context *context, + 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 copyTexture(const gl::Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + GLenum type, + size_t sourceLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + gl::Error copySubTexture(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + size_t sourceLevel, + const gl::Rectangle &sourceArea, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const gl::Texture *source) override; + + gl::Error setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; + + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; + + gl::Error getRenderTarget(const gl::Context *context, + 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; - 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); + gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outTexStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) 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); + bool isImageComplete(const gl::ImageIndex &index) const override; + gl::Error updateStorageFaceLevel(const gl::Context *context, int faceIndex, int level); - void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size); + gl::Error redefineImage(const gl::Context *context, + int faceIndex, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); - ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + std::array<TexLevelsArray<std::unique_ptr<ImageD3D>>, 6> mImageArray; }; class TextureD3D_3D : public TextureD3D { public: - TextureD3D_3D(RendererD3D *renderer); - virtual ~TextureD3D_3D(); + TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_3D() override; - virtual ImageD3D *getImage(int level, int layer) const; - virtual ImageD3D *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; + gl::Error onDestroy(const gl::Context *context) override; + + ImageD3D *getImage(int level, int layer) const; + ImageD3D *getImage(const gl::ImageIndex &index) const override; + GLsizei getLayerCount(int level) const override; GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -261,110 +477,213 @@ class TextureD3D_3D : public TextureD3D 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, + gl::Error setImage(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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, + gl::Error copySubImage(const gl::Context *context, + 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 setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; - gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual gl::ImageIndexIterator imageIterator() const; - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; - virtual bool isValidIndex(const gl::ImageIndex &index) const; + 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; + 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); + gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) override; bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - gl::Error updateStorageLevel(int level); + bool isImageComplete(const gl::ImageIndex &index) const override; + gl::Error updateStorageLevel(const gl::Context *context, int level); - void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + gl::Error redefineImage(const gl::Context *context, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); - ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelsArray<std::unique_ptr<ImageD3D>> mImageArray; }; class TextureD3D_2DArray : public TextureD3D { public: - TextureD3D_2DArray(RendererD3D *renderer); - virtual ~TextureD3D_2DArray(); + TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_2DArray() override; + + gl::Error onDestroy(const gl::Context *context) override; virtual ImageD3D *getImage(int level, int layer) const; - virtual ImageD3D *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; + ImageD3D *getImage(const gl::ImageIndex &index) const override; + GLsizei getLayerCount(int level) const override; 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, + gl::Error setImage(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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, + gl::Error copySubImage(const gl::Context *context, + 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 setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; - gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::ImageIndexIterator imageIterator() const override; + gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override; + bool isValidIndex(const gl::ImageIndex &index) const override; - 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); + gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) override; bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - gl::Error updateStorageLevel(int level); + bool isImageComplete(const gl::ImageIndex &index) const override; + gl::Error updateStorageLevel(const gl::Context *context, int level); void deleteImages(); - void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + gl::Error redefineImage(const gl::Context *context, + GLint level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); // 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 @@ -374,6 +693,199 @@ class TextureD3D_2DArray : public TextureD3D 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + GLenum target, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(const gl::Context *context, + GLenum target, + size_t levels, + GLenum internalFormat, + const gl::Extents &size) override; + + gl::Error setImageExternal(const gl::Context *context, + GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; + + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; + + gl::Error getRenderTarget(const gl::Context *context, + 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(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outTexStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; + + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) override; + + bool isImageComplete(const gl::ImageIndex &index) const override; +}; + +class TextureD3D_2DMultisample : public TextureD3D +{ + public: + TextureD3D_2DMultisample(const gl::TextureState &data, RendererD3D *renderer); + ~TextureD3D_2DMultisample() override; + + ImageD3D *getImage(const gl::ImageIndex &index) const override; + gl::Error setImage(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + 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(const gl::Context *context, + GLenum target, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(const gl::Context *context, + GLenum target, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorageMultisample(const gl::Context *context, + GLenum target, + GLsizei samples, + GLint internalFormat, + const gl::Extents &size, + bool fixedSampleLocations) override; + + gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override; + gl::Error releaseTexImage(const gl::Context *context) override; + + gl::Error setEGLImageTarget(const gl::Context *context, + GLenum target, + egl::Image *image) override; + + gl::Error getRenderTarget(const gl::Context *context, + 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; + + GLsizei getLayerCount(int level) const override; + + protected: + void markAllImagesDirty() override; + + private: + gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override; + gl::Error createCompleteStorage(bool renderTarget, + TexStoragePointer *outTexStorage) const override; + gl::Error setCompleteTexStorage(const gl::Context *context, + TextureStorage *newCompleteTexStorage) override; + + gl::Error updateStorage(const gl::Context *context) override; + gl::Error initMipmapImages(const gl::Context *context) override; + + bool isImageComplete(const gl::ImageIndex &index) const override; +}; } #endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp deleted file mode 100644 index abb83a14d5..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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.cpp: Shared members of abstract rx::TextureStorage class. - -#include "libANGLE/renderer/d3d/TextureStorage.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/renderer/d3d/RenderTargetD3D.h" -#include "libANGLE/renderer/Renderer.h" -#include "libANGLE/Renderbuffer.h" -#include "libANGLE/Texture.h" - -#include "common/debug.h" -#include "common/mathutil.h" - -namespace rx -{ - -TextureStorage::TextureStorage() - : mFirstRenderTargetSerial(0), - mRenderTargetSerialsLayerStride(0) -{} - -void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) -{ - mFirstRenderTargetSerial = RenderTargetD3D::issueSerials(rtSerialsToReserve); - mRenderTargetSerialsLayerStride = rtSerialsLayerStride; -} - -unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const -{ - unsigned int layerOffset = (index.hasLayer() ? (static_cast<unsigned int>(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0); - return mFirstRenderTargetSerial + static_cast<unsigned int>(index.mipIndex) + layerOffset; -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h index 417237495d..383fbc2141 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h @@ -9,20 +9,19 @@ #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 "libANGLE/angletypes.h" #include <GLES2/gl2.h> #include <stdint.h> namespace gl { +class Context; struct ImageIndex; struct Box; struct PixelUnpackState; -} +} // namespace gl namespace rx { @@ -36,23 +35,48 @@ class TextureStorage : angle::NonCopyable TextureStorage() {} virtual ~TextureStorage() {} + virtual gl::Error onDestroy(const gl::Context *context); + 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 getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) = 0; + virtual gl::Error generateMipmap(const gl::Context *context, + 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; + virtual gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) = 0; + virtual gl::Error setData(const gl::Context *context, + 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); } + virtual gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture); }; +inline gl::Error TextureStorage::onDestroy(const gl::Context *context) +{ + return gl::NoError(); } +inline gl::Error TextureStorage::useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) +{ + return gl::NoError(); +} + +using TexStoragePointer = angle::UniqueObjectPointer<TextureStorage, gl::Context>; + +} // namespace rx + #endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp deleted file mode 100644 index 80a4ec3ae1..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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/TransformFeedbackD3D.h" - -namespace rx -{ - -TransformFeedbackD3D::TransformFeedbackD3D() -{ -} - -TransformFeedbackD3D::~TransformFeedbackD3D() -{ -} - -void TransformFeedbackD3D::begin(GLenum primitiveMode) -{ -} - -void TransformFeedbackD3D::end() -{ -} - -void TransformFeedbackD3D::pause() -{ -} - -void TransformFeedbackD3D::resume() -{ -} - -void TransformFeedbackD3D::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) -{ -} - -void TransformFeedbackD3D::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) -{ -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h deleted file mode 100644 index 6925966153..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// 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.h: Implements the abstract rx::TransformFeedbackImpl class. - -#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ -#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ - -#include "libANGLE/renderer/TransformFeedbackImpl.h" -#include "libANGLE/angletypes.h" - -namespace rx -{ - -class TransformFeedbackD3D : public TransformFeedbackImpl -{ - public: - TransformFeedbackD3D(); - virtual ~TransformFeedbackD3D(); - - 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; -}; - -} - -#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp deleted file mode 100644 index f2654d34e3..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp +++ /dev/null @@ -1,397 +0,0 @@ -// -// 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()); - - // "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; - } - - for (const PackedVarying &packedVarying : packedVaryings) - { - const auto &varying = *packedVarying.varying; - - // Make sure transform feedback varyings aren't optimized out. - if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0) - { - bool found = false; - 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h deleted file mode 100644 index ca4640b000..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h +++ /dev/null @@ -1,175 +0,0 @@ -// -// 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp index 9efee9db7c..7c2d5aec70 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -8,18 +8,19 @@ // 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" -#include "common/mathutil.h" - namespace rx { +// VertexBuffer Implementation unsigned int VertexBuffer::mNextSerial = 1; -VertexBuffer::VertexBuffer() +VertexBuffer::VertexBuffer() : mRefCount(1) { updateSerial(); } @@ -38,19 +39,34 @@ unsigned int VertexBuffer::getSerial() const return mSerial; } -VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic) - : mFactory(factory) +void VertexBuffer::addRef() { - mDynamic = dynamic; - mWritePosition = 0; - mReservedSpace = 0; + mRefCount++; +} + +void VertexBuffer::release() +{ + ASSERT(mRefCount > 0); + mRefCount--; + + if (mRefCount == 0) + { + delete this; + } +} - mVertexBuffer = factory->createVertexBuffer(); +// VertexBufferInterface Implementation +VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic) + : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic) +{ } VertexBufferInterface::~VertexBufferInterface() { - delete mVertexBuffer; + if (mVertexBuffer) + { + mVertexBuffer->release(); + } } unsigned int VertexBufferInterface::getSerial() const @@ -69,181 +85,172 @@ gl::Error VertexBufferInterface::setBufferSize(unsigned int size) { return mVertexBuffer->initialize(size, mDynamic); } - else + + return mVertexBuffer->setBufferSize(size); +} + +gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired( + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const +{ + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances), + spaceRequired); + + // Align to 16-byte boundary + unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u); + + if (alignedSpaceRequired < spaceRequired) { - return mVertexBuffer->setBufferSize(size); + return gl::OutOfMemory() + << "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired."; } + + return alignedSpaceRequired; } -unsigned int VertexBufferInterface::getWritePosition() const +gl::Error VertexBufferInterface::discard() { - return mWritePosition; + return mVertexBuffer->discard(); } -void VertexBufferInterface::setWritePosition(unsigned int writePosition) +VertexBuffer *VertexBufferInterface::getVertexBuffer() const { - mWritePosition = writePosition; + return mVertexBuffer; } -gl::Error VertexBufferInterface::discard() +// StreamingVertexBufferInterface Implementation +StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, + std::size_t initialSize) + : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0) { - return mVertexBuffer->discard(); + // TODO(jmadill): Make an initialize method that can return an error. + ANGLE_SWALLOW_ERR(setBufferSize(static_cast<unsigned int>(initialSize))); } -gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, - GLenum currentValueType, - GLint start, - GLsizei count, - GLsizei instances, - unsigned int *outStreamOffset, - const uint8_t *sourceData) +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() { - gl::Error error(GL_NO_ERROR); +} - unsigned int spaceRequired; - error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired); - if (error.isError()) +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) { - return error; + ANGLE_TRY(discard()); + mWritePosition = 0; } - // Align to 16-byte boundary - unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u); + return gl::NoError(); +} + +gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData) +{ + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired); // Protect against integer overflow - if (!IsUnsignedAdditionSafe(mWritePosition, alignedSpaceRequired) || - alignedSpaceRequired < spaceRequired) + 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."); + return gl::OutOfMemory() + << "Internal error, new vertex buffer write position would overflow."; } - error = reserveSpace(mReservedSpace); - if (error.isError()) - { - return error; - } + ANGLE_TRY(reserveSpace(mReservedSpace)); mReservedSpace = 0; - error = mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count, instances, mWritePosition, sourceData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, currentValueType, start, count, + instances, mWritePosition, sourceData)); if (outStreamOffset) { *outStreamOffset = mWritePosition; } - mWritePosition += alignedSpaceRequired; + mWritePosition += spaceRequired; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) +gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) { - gl::Error error(GL_NO_ERROR); - - unsigned int requiredSpace; - error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace); - if (error.isError()) - { - return error; - } + unsigned int requiredSpace = 0; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances), + requiredSpace); // Align to 16-byte boundary - unsigned int alignedRequiredSpace = roundUp(requiredSpace, 16u); + auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u); + alignedRequiredSpace += mReservedSpace; // Protect against integer overflow - if (!IsUnsignedAdditionSafe(mReservedSpace, alignedRequiredSpace) || - alignedRequiredSpace < requiredSpace) + 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); + return gl::OutOfMemory() + << "Unable to reserve " << requiredSpace + << " extra bytes in internal vertex buffer, it would result in an overflow."; } - mReservedSpace += alignedRequiredSpace; + mReservedSpace = alignedRequiredSpace.ValueOrDie(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -VertexBuffer* VertexBufferInterface::getVertexBuffer() const +// StaticVertexBufferInterface Implementation +StaticVertexBufferInterface::AttributeSignature::AttributeSignature() + : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0) { - return mVertexBuffer; } -bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, - GLenum currentValueType) const +bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute( + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) const { - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; + size_t attribStride = ComputeVertexAttributeStride(attrib, binding); - if (!storage || !storage->supportsDirectBinding()) + if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride || + normalized != attrib.normalized || pureInteger != attrib.pureInteger) { 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; - bool requiresConversion = false; - - if (attrib.type != GL_FLOAT) - { - gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); - - unsigned int outputElementSize; - getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - alignment = std::min<size_t>(outputElementSize, 4); - - // TODO(jmadill): add VertexFormatCaps - requiresConversion = (mFactory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0; - } - - bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) && - (static_cast<size_t>(attrib.offset) % alignment == 0); - - return !requiresConversion && isAligned; + size_t attribOffset = + (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride); + return (offset == attribOffset); } -StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize) - : VertexBufferInterface(factory, true) +void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) { - setBufferSize(static_cast<unsigned int>(initialSize)); -} - -StreamingVertexBufferInterface::~StreamingVertexBufferInterface() -{ -} - -gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) -{ - unsigned int curBufferSize = getBufferSize(); - if (size > curBufferSize) - { - gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2)); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - else if (getWritePosition() + size > curBufferSize) - { - gl::Error error = discard(); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - - return gl::Error(GL_NO_ERROR); + type = attrib.type; + size = attrib.size; + normalized = attrib.normalized; + pureInteger = attrib.pureInteger; + offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding)); + offset = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % + ComputeVertexAttributeStride(attrib, binding); } StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) - : VertexBufferInterface(factory, false), mIsCommitted(false) + : VertexBufferInterface(factory, false) { } @@ -251,82 +258,36 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface() { } -bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset) +bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) const { - for (unsigned int element = 0; element < mCache.size(); element++) - { - size_t attribStride = ComputeVertexAttributeStride(attrib); - - if (mCache[element].type == attrib.type && mCache[element].size == attrib.size && - mCache[element].stride == attribStride && - mCache[element].normalized == attrib.normalized && - mCache[element].pureInteger == attrib.pureInteger) - { - size_t offset = (static_cast<size_t>(attrib.offset) % attribStride); - if (mCache[element].attributeOffset == offset) - { - if (outStreamOffset) - { - *outStreamOffset = mCache[element].streamOffset; - } - return true; - } - } - } - - return false; + return mSignature.matchesAttribute(attrib, binding); } -gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size) +void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) { - unsigned int curSize = getBufferSize(); - if (curSize == 0) - { - return setBufferSize(size); - } - else if (curSize >= size) - { - return gl::Error(GL_NO_ERROR); - } - else - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized."); - } + return mSignature.set(attrib, binding); } -gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, - GLenum currentValueType, - GLint start, - GLsizei count, - GLsizei instances, - unsigned int *outStreamOffset, - const uint8_t *sourceData) +gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLint start, + GLsizei count, + GLsizei instances, + const uint8_t *sourceData) { - unsigned int streamOffset; - gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValueType, start, count, instances, &streamOffset, sourceData); - if (error.isError()) - { - return error; - } + unsigned int spaceRequired = 0; + ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired); + ANGLE_TRY(setBufferSize(spaceRequired)); - size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib); - VertexElement element = { attrib.type, attrib.size, static_cast<GLuint>(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; - mCache.push_back(element); - - if (outStreamOffset) - { - *outStreamOffset = streamOffset; - } + ASSERT(attrib.enabled); + ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, GL_NONE, start, count, + instances, 0, sourceData)); - return gl::Error(GL_NO_ERROR); + mSignature.set(attrib, binding); + mVertexBuffer->hintUnmapResource(); + return gl::NoError(); } -void StaticVertexBufferInterface::commit() -{ - if (getBufferSize() > 0) - { - mIsCommitted = true; - } -} -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h index 692b6ac506..df8085d3cb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -22,6 +22,7 @@ namespace gl { struct VertexAttribute; +class VertexBinding; struct VertexAttribCurrentValueData; } @@ -29,23 +30,25 @@ 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 ~VertexBuffer(); virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, GLsizei instances, unsigned int offset, const uint8_t *sourceData) = 0; - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const = 0; virtual unsigned int getBufferSize() const = 0; virtual gl::Error setBufferSize(unsigned int size) = 0; @@ -56,12 +59,18 @@ class VertexBuffer : angle::NonCopyable // 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 @@ -70,42 +79,24 @@ class VertexBufferInterface : angle::NonCopyable VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic); virtual ~VertexBufferInterface(); - gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); - unsigned int getBufferSize() const; + bool empty() const { return getBufferSize() == 0; } unsigned int getSerial() const; - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, - GLenum currentValueType, - GLint start, - GLsizei count, - GLsizei instances, - unsigned int *outStreamOffset, - const uint8_t *sourceData); - - bool directStoragePossible(const gl::VertexAttribute &attrib, - GLenum currentValueType) const; - - VertexBuffer* getVertexBuffer() const; + VertexBuffer *getVertexBuffer() const; protected: - virtual gl::Error reserveSpace(unsigned int size) = 0; - - unsigned int getWritePosition() const; - void setWritePosition(unsigned int writePosition); - gl::Error discard(); gl::Error setBufferSize(unsigned int size); - private: + gl::ErrorOrResult<unsigned int> getSpaceRequired(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const; BufferFactoryD3D *const mFactory; - - VertexBuffer* mVertexBuffer; - - unsigned int mWritePosition; - unsigned int mReservedSpace; + VertexBuffer *mVertexBuffer; bool mDynamic; }; @@ -113,53 +104,72 @@ class StreamingVertexBufferInterface : public VertexBufferInterface { public: StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize); - ~StreamingVertexBufferInterface(); + ~StreamingVertexBufferInterface() override; - protected: + gl::Error storeDynamicAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData); + + gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, + const gl::VertexBinding &binding, + 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(); + ~StaticVertexBufferInterface() override; - gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, - GLenum currentValueType, - GLint start, - GLsizei count, - GLsizei instances, - unsigned int *outStreamOffset, - const uint8_t *sourceData) override; - - bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); + // Warning: you should ensure binding really matches attrib.bindingIndex before using these + // functions. + gl::Error storeStaticAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLint start, + GLsizei count, + GLsizei instances, + const uint8_t *sourceData); - // If a static vertex buffer is committed then no more attribute data can be added to it - // A new static vertex buffer should be created instead - void commit(); - bool isCommitted() { return mIsCommitted; } + bool matchesAttribute(const gl::VertexAttribute &attribute, + const gl::VertexBinding &binding) const; - protected: - gl::Error reserveSpace(unsigned int size); + void setAttribute(const gl::VertexAttribute &attribute, const gl::VertexBinding &binding); private: - struct VertexElement + class AttributeSignature final : angle::NonCopyable { + public: + AttributeSignature(); + + bool matchesAttribute(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) const; + + void set(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding); + + private: GLenum type; GLuint size; GLuint stride; bool normalized; bool pureInteger; - size_t attributeOffset; - - unsigned int streamOffset; + size_t offset; }; - bool mIsCommitted; - std::vector<VertexElement> mCache; + AttributeSignature mSignature; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index b392d0f4da..54ad5e54f5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -9,25 +9,38 @@ #include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "common/bitset_utils.h" #include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" #include "libANGLE/Program.h" #include "libANGLE/State.h" -#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexArray.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/VertexBuffer.h" -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 }; -} +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 +}; -static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size) +// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. +int ElementsInBuffer(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + unsigned int size) { // Size cannot be larger than a GLsizei if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) @@ -35,15 +48,139 @@ static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size size = static_cast<unsigned int>(std::numeric_limits<int>::max()); } - GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib)); - return (size - attrib.offset % stride + + GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding)); + GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding)); + return (size - offset % stride + (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) / stride; } -VertexDataManager::CurrentValueState::CurrentValueState() - : buffer(nullptr), - offset(0) +// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. +bool DirectStoragePossible(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding) +{ + // Current value attribs may not use direct storage. + if (!attrib.enabled) + { + return false; + } + + gl::Buffer *buffer = binding.getBuffer().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; + + // TODO(jmadill): add VertexFormatCaps + BufferFactoryD3D *factory = bufferD3D->getFactory(); + + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib); + + // CPU-converted vertex data must be converted (naturally). + if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0) + { + return false; + } + + if (attrib.type != GL_FLOAT) + { + auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, binding, 1, 0); + if (errorOrElementSize.isError()) + { + ERR() << "Unlogged error in DirectStoragePossible."; + return false; + } + + alignment = std::min<size_t>(errorOrElementSize.getResult(), 4); + } + + GLintptr offset = ComputeVertexAttributeOffset(attrib, binding); + // Final alignment check - unaligned data must be converted. + return (static_cast<size_t>(ComputeVertexAttributeStride(attrib, binding)) % alignment == 0) && + (static_cast<size_t>(offset) % alignment == 0); +} +} // anonymous namespace + +TranslatedAttribute::TranslatedAttribute() + : active(false), + attribute(nullptr), + binding(nullptr), + currentValueType(GL_NONE), + baseOffset(0), + usesFirstVertexOffset(false), + stride(0), + vertexBuffer(), + storage(nullptr), + serial(0), + divisor(0) +{ +} + +TranslatedAttribute::TranslatedAttribute(const TranslatedAttribute &other) = default; + +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(); +} + +// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. +VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding) +{ + // 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 = binding.getBuffer().get(); + if (!buffer) + { + return VertexStorageType::DYNAMIC; + } + + // Check if the buffer supports direct storage. + if (DirectStoragePossible(attrib, binding)) + { + 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(), offset(0) { data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN(); data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN(); @@ -54,379 +191,456 @@ VertexDataManager::CurrentValueState::CurrentValueState() VertexDataManager::CurrentValueState::~CurrentValueState() { - SafeDelete(buffer); } VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) - : mFactory(factory), - mStreamingBuffer(nullptr), - // TODO(jmadill): use context caps - mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS) + : mFactory(factory), mStreamingBuffer(), mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS) { - mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE); - - if (!mStreamingBuffer) - { - ERR("Failed to allocate the streaming vertex buffer."); - } - - // TODO(jmadill): use context caps - mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); - mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); } VertexDataManager::~VertexDataManager() { - SafeDelete(mStreamingBuffer); } -void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes) +gl::Error VertexDataManager::initialize() { - mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); - - for (const TranslatedAttribute *translated : mActiveEnabledAttributes) + mStreamingBuffer.reset( + new StreamingVertexBufferInterface(mFactory, INITIAL_STREAM_BUFFER_SIZE)); + if (!mStreamingBuffer) { - gl::Buffer *buffer = translated->attribute->buffer.get(); - BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; - StaticVertexBufferInterface *staticBuffer = - storage - ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE) - : nullptr; - - if (staticBuffer) - { - // Commit all the static vertex buffers. This fixes them in size/contents, and forces - // ANGLE to use a new static buffer (or recreate the static buffers) next time - staticBuffer->commit(); - - staticBuffer->getVertexBuffer()->hintUnmapResource(); - } + return gl::OutOfMemory() << "Failed to allocate the streaming vertex buffer."; } - for (auto ¤tValue : mCurrentValueCache) - { - if (currentValue.buffer != nullptr) - { - currentValue.buffer->getVertexBuffer()->hintUnmapResource(); - } - } + return gl::NoError(); } -gl::Error VertexDataManager::prepareVertexData(const gl::State &state, +void VertexDataManager::deinitialize() +{ + mStreamingBuffer.reset(); + mCurrentValueCache.clear(); +} + +gl::Error VertexDataManager::prepareVertexData(const gl::Context *context, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances) { - if (!mStreamingBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); - } + ASSERT(mStreamingBuffer); - // Compute active enabled and active disable attributes, for speed. - // TODO(jmadill): don't recompute if there was no state change + const gl::State &state = context->getGLState(); const gl::VertexArray *vertexArray = state.getVertexArray(); - const gl::Program *program = state.getProgram(); const auto &vertexAttributes = vertexArray->getVertexAttributes(); + const auto &vertexBindings = vertexArray->getVertexBindings(); + + mDynamicAttribsMaskCache.reset(); + const gl::Program *program = state.getProgram(); - mActiveEnabledAttributes.clear(); - mActiveDisabledAttributes.clear(); translatedAttribs->clear(); for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { - if (program->isAttribLocationActive(attribIndex)) - { - // Resize automatically puts in empty attribs - translatedAttribs->resize(attribIndex + 1); + // Skip attrib locations the program doesn't use. + if (!program->isAttribLocationActive(attribIndex)) + continue; + + const auto &attrib = vertexAttributes[attribIndex]; + const auto &binding = vertexBindings[attrib.bindingIndex]; - TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; + // Resize automatically puts in empty attribs + translatedAttribs->resize(attribIndex + 1); - // Record the attribute now - translated->active = true; - translated->attribute = &vertexAttributes[attribIndex]; - translated->currentValueType = - state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type; - translated->divisor = vertexAttributes[attribIndex].divisor; + TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; + auto currentValueData = state.getVertexAttribCurrentValue(attribIndex); - if (vertexAttributes[attribIndex].enabled) + // Record the attribute now + translated->active = true; + translated->attribute = &attrib; + translated->binding = &binding; + translated->currentValueType = currentValueData.Type; + translated->divisor = binding.getDivisor(); + + switch (ClassifyAttributeStorage(attrib, binding)) + { + case VertexStorageType::STATIC: { - mActiveEnabledAttributes.push_back(translated); - - gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get(); - if (buffer) - { - // Also reinitialize static buffers which didn't contain matching data - // last time they were used - BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); - bufferImpl->reinitOutOfDateStaticData(); - } + // Store static attribute. + ANGLE_TRY(StoreStaticAttrib(context, translated)); + break; } - else + 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: { - mActiveDisabledAttributes.push_back(attribIndex); + ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex)); + break; } + default: + UNREACHABLE(); + break; } } - // Reserve the required space in the buffers - for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) + if (mDynamicAttribsMaskCache.none()) { - gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances); - if (error.isError()) - { - return error; - } + return gl::NoError(); } - // Perform the vertex data translations - for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) + ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start, + count, instances)); + + PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count); + + return gl::NoError(); +} + +// static +void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib) +{ + ASSERT(directAttrib->attribute && directAttrib->binding); + const auto &attrib = *directAttrib->attribute; + const auto &binding = *directAttrib->binding; + + gl::Buffer *buffer = binding.getBuffer().get(); + ASSERT(buffer); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + + ASSERT(DirectStoragePossible(attrib, binding)); + directAttrib->vertexBuffer.set(nullptr); + directAttrib->storage = bufferD3D; + directAttrib->serial = bufferD3D->getSerial(); + directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding)); + directAttrib->baseOffset = + static_cast<unsigned int>(ComputeVertexAttributeOffset(attrib, binding)); + + // Instanced vertices do not apply the 'start' offset + directAttrib->usesFirstVertexOffset = (binding.getDivisor() == 0); +} + +// static +gl::Error VertexDataManager::StoreStaticAttrib(const gl::Context *context, + TranslatedAttribute *translated) +{ + ASSERT(translated->attribute && translated->binding); + const auto &attrib = *translated->attribute; + const auto &binding = *translated->binding; + + gl::Buffer *buffer = binding.getBuffer().get(); + ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib, binding)); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + + // Compute source data pointer + const uint8_t *sourceData = nullptr; + const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding)); + + ANGLE_TRY(bufferD3D->getData(context, &sourceData)); + sourceData += offset; + + unsigned int streamOffset = 0; + + translated->storage = nullptr; + ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, binding, 1, 0), + translated->stride); + + auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding); + ASSERT(staticBuffer); + + if (staticBuffer->empty()) { - gl::Error error = storeAttribute(activeAttrib, start, count, instances); + // Convert the entire buffer + int totalCount = + ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize())); + int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding)); - if (error.isError()) - { - hintUnmapAllResources(vertexAttributes); - return error; - } + ANGLE_TRY(staticBuffer->storeStaticAttribute(attrib, binding, -startIndex, totalCount, 0, + sourceData)); } - for (size_t attribIndex : mActiveDisabledAttributes) + unsigned int firstElementOffset = + (static_cast<unsigned int>(offset) / + static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) * + translated->stride; + + VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer(); + + CheckedNumeric<unsigned int> checkedOffset(streamOffset); + checkedOffset += firstElementOffset; + + if (!checkedOffset.IsValid()) { - if (mCurrentValueCache[attribIndex].buffer == nullptr) - { - mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); - } + return gl::InternalError() << "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 = (binding.getDivisor() == 0); - gl::Error error = storeCurrentValue( - state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)), - &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]); - if (error.isError()) + return gl::NoError(); +} + +gl::Error VertexDataManager::storeDynamicAttribs( + const gl::Context *context, + 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) { - hintUnmapAllResources(vertexAttributes); - return error; + ASSERT(mStreamingBuffer); } + ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); } + + private: + StreamingVertexBufferInterface *mStreamingBuffer; + }; + + // Will trigger unmapping on return. + StreamingBufferUnmapper localUnmapper(mStreamingBuffer.get()); + + // Reserve the required space for the dynamic buffers. + for (auto attribIndex : dynamicAttribsMask) + { + const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; + ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, start, count, instances)); + } + + // Store dynamic attributes + for (auto attribIndex : dynamicAttribsMask) + { + auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; + ANGLE_TRY(storeDynamicAttrib(context, dynamicAttrib, start, count, instances)); } - // Hint to unmap all the resources - hintUnmapAllResources(vertexAttributes); + return gl::NoError(); +} - for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) +void VertexDataManager::PromoteDynamicAttribs( + const gl::Context *context, + const std::vector<TranslatedAttribute> &translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLsizei count) +{ + for (auto attribIndex : dynamicAttribsMask) { - gl::Buffer *buffer = activeAttrib->attribute->buffer.get(); + const auto &dynamicAttrib = translatedAttribs[attribIndex]; + ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding); + const auto &binding = *dynamicAttrib.binding; + gl::Buffer *buffer = binding.getBuffer().get(); if (buffer) { BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); - size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute); - bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); + size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute); + bufferD3D->promoteStaticUsage(context, count * static_cast<int>(typeSize)); } } - - return gl::Error(GL_NO_ERROR); } gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, + GLint start, GLsizei count, GLsizei instances) const { - const gl::VertexAttribute &attrib = *translatedAttrib.attribute; - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = - bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY) - : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - - if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType)) + ASSERT(translatedAttrib.attribute && translatedAttrib.binding); + const auto &attrib = *translatedAttrib.attribute; + const auto &binding = *translatedAttrib.binding; + + ASSERT(!DirectStoragePossible(attrib, binding)); + + gl::Buffer *buffer = binding.getBuffer().get(); + BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; + ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr); + + size_t totalCount = gl::ComputeVertexBindingElementCount( + binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances)); + // TODO(jiajia.qin@intel.com): force the index buffer to clamp any out of range indices instead + // of invalid operation here. + if (bufferD3D) { - if (staticBuffer) + // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing + // a non-instanced draw call + GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start; + int64_t maxVertexCount = + static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount); + int elementsInBuffer = + ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize())); + + if (maxVertexCount > elementsInBuffer) { - if (staticBuffer->getBufferSize() == 0) - { - int totalCount = - ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())); - gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); - if (error.isError()) - { - return error; - } - } - } - else - { - size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); - ASSERT(!bufferImpl || - ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >= - static_cast<int>(totalCount)); - - gl::Error error = mStreamingBuffer->reserveVertexSpace( - attrib, static_cast<GLsizei>(totalCount), instances); - if (error.isError()) - { - return error; - } + return gl::InvalidOperation() << "Vertex buffer is not big enough for the draw call."; } } - - return gl::Error(GL_NO_ERROR); + return mStreamingBuffer->reserveVertexSpace(attrib, binding, static_cast<GLsizei>(totalCount), + instances); } -gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, - GLint start, - GLsizei count, - GLsizei instances) +gl::Error VertexDataManager::storeDynamicAttrib(const gl::Context *context, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances) { - const gl::VertexAttribute &attrib = *translated->attribute; + ASSERT(translated->attribute && translated->binding); + const auto &attrib = *translated->attribute; + const auto &binding = *translated->binding; - gl::Buffer *buffer = attrib.buffer.get(); + gl::Buffer *buffer = binding.getBuffer().get(); ASSERT(buffer || attrib.pointer); ASSERT(attrib.enabled); - BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = - storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType); + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; // Instanced vertices do not apply the 'start' offset - GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start); - - translated->vertexBuffer = vertexBuffer->getVertexBuffer(); - - if (directStorage) - { - translated->storage = storage; - translated->serial = storage->getSerial(); - translated->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib)); - translated->offset = static_cast<unsigned int>(attrib.offset + translated->stride * firstVertexIndex); - - return gl::Error(GL_NO_ERROR); - } + GLint firstVertexIndex = (binding.getDivisor() > 0 ? 0 : start); // Compute source data pointer const uint8_t *sourceData = nullptr; if (buffer) { - gl::Error error = storage->getData(&sourceData); - if (error.isError()) - { - return error; - } - sourceData += static_cast<int>(attrib.offset); + ANGLE_TRY(storage->getData(context, &sourceData)); + sourceData += static_cast<int>(ComputeVertexAttributeOffset(attrib, binding)); } else { + // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state. + // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt sourceData = static_cast<const uint8_t*>(attrib.pointer); } unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; - if (staticBuffer) - { - gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - if (error.isError()) - { - return error; - } - - if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) - { - // Convert the entire buffer - int totalCount = - ElementsInBuffer(attrib, static_cast<unsigned int>(storage->getSize())); - int startIndex = static_cast<int>(attrib.offset) / - static_cast<int>(ComputeVertexAttributeStride(attrib)); - - error = staticBuffer->storeVertexAttributes(attrib, - translated->currentValueType, - -startIndex, - totalCount, - 0, - &streamOffset, - sourceData); - if (error.isError()) - { - return error; - } - } + translated->storage = nullptr; + ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, 1, 0), translated->stride); - unsigned int firstElementOffset = - (static_cast<unsigned int>(attrib.offset) / - static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) * - outputElementSize; - ASSERT(attrib.divisor == 0 || firstVertexIndex == 0); - unsigned int startOffset = firstVertexIndex * outputElementSize; - if (streamOffset + firstElementOffset + startOffset < streamOffset) - { - return gl::Error(GL_OUT_OF_MEMORY); - } + size_t totalCount = gl::ComputeVertexBindingElementCount( + binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances)); - streamOffset += firstElementOffset + startOffset; - } - else - { - size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); - gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute( + attrib, binding, translated->currentValueType, firstVertexIndex, + static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData)); - error = mStreamingBuffer->storeVertexAttributes( - attrib, translated->currentValueType, firstVertexIndex, - static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData); - if (error.isError()) - { - return error; - } - } + VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer(); - translated->storage = nullptr; + translated->vertexBuffer.set(vertexBuffer); translated->serial = vertexBuffer->getSerial(); - translated->stride = outputElementSize; - translated->offset = streamOffset; + translated->baseOffset = streamOffset; + translated->usesFirstVertexOffset = false; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, TranslatedAttribute *translated, - CurrentValueState *cachedState) + size_t attribIndex) { + CurrentValueState *cachedState = &mCurrentValueCache[attribIndex]; + auto &buffer = cachedState->buffer; + + if (!buffer) + { + buffer.reset(new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE)); + } + if (cachedState->data != currentValue) { - const gl::VertexAttribute &attrib = *translated->attribute; + ASSERT(translated->attribute && translated->binding); + const auto &attrib = *translated->attribute; + const auto &binding = *translated->binding; - gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->reserveVertexSpace(attrib, binding, 1, 0)); const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); unsigned int streamOffset; - error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buffer->storeDynamicAttribute(attrib, binding, currentValue.Type, 0, 1, 0, + &streamOffset, sourceData)); + + buffer->getVertexBuffer()->hintUnmapResource(); cachedState->data = currentValue; cachedState->offset = streamOffset; } - translated->storage = NULL; - translated->vertexBuffer = cachedState->buffer->getVertexBuffer(); - translated->serial = cachedState->buffer->getSerial(); + 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; - translated->stride = 0; - translated->offset = static_cast<unsigned int>(cachedState->offset); + return gl::NoError(); +} - return gl::Error(GL_NO_ERROR); +// 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h index fb349c4cc2..694366deb7 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -10,14 +10,16 @@ #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" -#include "common/angleutils.h" namespace gl { class State; struct VertexAttribute; +class VertexBinding; struct VertexAttribCurrentValueData; } @@ -28,81 +30,123 @@ 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() - : active(false), - attribute(NULL), - currentValueType(GL_NONE), - offset(0), - stride(0), - vertexBuffer(NULL), - storage(NULL), - serial(0), - divisor(0) - {} + TranslatedAttribute(); + TranslatedAttribute(const TranslatedAttribute &other); + + // 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; + const gl::VertexBinding *binding; GLenum currentValueType; - unsigned int offset; + unsigned int baseOffset; + bool usesFirstVertexOffset; unsigned int stride; // 0 means not to advance the read pointer at all - VertexBuffer *vertexBuffer; + 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, + const gl::VertexBinding &binding); + class VertexDataManager : angle::NonCopyable { public: VertexDataManager(BufferFactoryD3D *factory); virtual ~VertexDataManager(); - gl::Error prepareVertexData(const gl::State &state, + gl::Error initialize(); + void deinitialize(); + + gl::Error prepareVertexData(const gl::Context *context, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances); + static void StoreDirectAttrib(TranslatedAttribute *directAttrib); + + static gl::Error StoreStaticAttrib(const gl::Context *context, TranslatedAttribute *translated); + + gl::Error storeDynamicAttribs(const gl::Context *context, + std::vector<TranslatedAttribute> *translatedAttribs, + const gl::AttributesMask &dynamicAttribsMask, + GLint start, + GLsizei count, + GLsizei instances); + + // Promote static usage of dynamic buffers. + static void PromoteDynamicAttribs(const gl::Context *context, + 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; + std::unique_ptr<StreamingVertexBufferInterface> buffer; gl::VertexAttribCurrentValueData data; size_t offset; }; gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, GLsizei count, + GLint start, GLsizei instances) const; - gl::Error storeAttribute(TranslatedAttribute *translated, - GLint start, - GLsizei count, - GLsizei instances); - - gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, - CurrentValueState *cachedState); - - void hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes); + gl::Error storeDynamicAttrib(const gl::Context *context, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances); BufferFactoryD3D *const mFactory; - StreamingVertexBufferInterface *mStreamingBuffer; + std::unique_ptr<StreamingVertexBufferInterface> mStreamingBuffer; std::vector<CurrentValueState> mCurrentValueCache; - - // Cache variables - std::vector<TranslatedAttribute *> mActiveEnabledAttributes; - std::vector<size_t> mActiveDisabledAttributes; + gl::AttributesMask mDynamicAttribsMaskCache; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h deleted file mode 100644 index 58f65f6496..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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 -{ - D3DCompilerWorkarounds() - : skipOptimization(false), useMaxOptimization(false), enableIEEEStrictness(false) - { - } - - bool skipOptimization; - bool useMaxOptimization; - - // IEEE strictness needs to be enabled for NANs to work. - bool enableIEEEStrictness; -}; - -struct WorkaroundsD3D -{ - WorkaroundsD3D() - : mrtPerfWorkaround(false), - setDataFasterThanImageUpload(false), - zeroMaxLodWorkaround(false), - useInstancedPointSpriteEmulation(false) - { - } - - // 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; - - bool setDataFasterThanImageUpload; - - // 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; - - // 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; -}; -} - -#endif // LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp deleted file mode 100644 index b1798454ca..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// 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. -// - -// copyimage.cpp: Defines image copying functions - -#include "libANGLE/renderer/d3d/copyimage.h" - -namespace rx -{ - -void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest) -{ - uint32_t argb = *reinterpret_cast<const uint32_t*>(source); - *reinterpret_cast<uint32_t*>(dest) = (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h deleted file mode 100644 index 189654ca39..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// 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. -// - -// copyimage.h: Defines image copying functions - -#ifndef LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ -#define LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ - -#include "common/mathutil.h" -#include "libANGLE/angletypes.h" - -#include <stdint.h> - -namespace rx -{ - -template <typename sourceType, typename colorDataType> -void ReadColor(const uint8_t *source, uint8_t *dest); - -template <typename destType, typename colorDataType> -void WriteColor(const uint8_t *source, uint8_t *dest); - -template <typename sourceType, typename destType, typename colorDataType> -void CopyPixel(const uint8_t *source, uint8_t *dest); - -void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest); - -} - -#include "copyimage.inl" - -#endif // LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl deleted file mode 100644 index 0498cf7750..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl +++ /dev/null @@ -1,32 +0,0 @@ -// -// 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. -// - -// copyimage.inl: Defines image copying functions - -namespace rx -{ - -template <typename sourceType, typename colorDataType> -inline void ReadColor(const uint8_t *source, uint8_t *dest) -{ - sourceType::readColor(reinterpret_cast<gl::Color<colorDataType>*>(dest), reinterpret_cast<const sourceType*>(source)); -} - -template <typename destType, typename colorDataType> -inline void WriteColor(const uint8_t *source, uint8_t *dest) -{ - destType::writeColor(reinterpret_cast<destType*>(dest), reinterpret_cast<const gl::Color<colorDataType>*>(source)); -} - -template <typename sourceType, typename destType, typename colorDataType> -inline void CopyPixel(const uint8_t *source, uint8_t *dest) -{ - colorDataType temp; - ReadColor<sourceType, colorDataType>(source, &temp); - WriteColor<destType, colorDataType>(&temp, dest); -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp index e951e13408..f032e888f1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -10,112 +10,404 @@ #include <float.h> +#include "common/utilities.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.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" +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/passthrougha2d11ps.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/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/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/passthroughr2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_ps.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/passthrough3d11vs.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/passthroughr3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.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/swizzlef2darrayps.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/swizzlei2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" -namespace rx +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; -namespace + 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; -DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) + 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) { - ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); - if (!texture) + 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 { - return DXGI_FORMAT_UNKNOWN; + StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize, + sourceRowPitch, destRowPitch, readOffset, writeOffset, + copySize, srcPixelStride, destPixelStride, sourceData, + destData); } +} - D3D11_TEXTURE2D_DESC desc; - texture->GetDesc(&desc); +using DepthStencilLoader = void(const float *, uint8_t *); - SafeRelease(texture); +void LoadDepth16(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 2u); +} - return desc.Format; +void LoadDepth24(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 3u); } -ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, - ID3D11Resource *source, unsigned int subresource, - const gl::Extents &size, unsigned int cpuAccessFlags) +void LoadStencilHelper(const float *source, uint8_t *dest) { - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = size.width; - stagingDesc.Height = size.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = GetTextureFormat(source); - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.CPUAccessFlags = cpuAccessFlags; - stagingDesc.MiscFlags = 0; - stagingDesc.BindFlags = 0; - - ID3D11Texture2D *stagingTexture = nullptr; - HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture); - if (FAILED(result)) + 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) { - ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); - return nullptr; + 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); + } } +} - context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, nullptr); +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); - return stagingTexture; + 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) +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; @@ -128,37 +420,49 @@ inline void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &s *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, +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); + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); - d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(outVertices); + 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); + *outStride = sizeof(d3d11::PositionTexCoordVertex); *outVertexCount = 4; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + *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, +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); + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); - d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast<d3d11::PositionLayerTexCoord3DVertex*>(outVertices); + d3d11::PositionLayerTexCoord3DVertex *vertices = + static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices); for (int i = 0; i < destSize.depth; i++) { @@ -173,24 +477,38 @@ void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); } - *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); *outVertexCount = destSize.depth * 6; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } -inline unsigned int GetSwizzleIndex(GLenum swizzle) +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; + 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; @@ -213,30 +531,50 @@ D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc() 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 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 }, +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}, }; -} // namespace +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::Shader::Shader() = default; + +Blit11::Shader::Shader(Shader &&other) = default; + +Blit11::Shader::~Shader() = default; + +Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default; Blit11::Blit11(Renderer11 *renderer) : mRenderer(renderer), mResourcesInitialized(false), - mVertexBuffer(nullptr), - mPointSampler(nullptr), - mLinearSampler(nullptr), - mScissorEnabledRasterizerState(nullptr), - mScissorDisabledRasterizerState(nullptr), - mDepthStencilState(nullptr), + mVertexBuffer(), + mPointSampler(), + mLinearSampler(), + mScissorEnabledRasterizerState(), + mScissorDisabledRasterizerState(), + mDepthStencilState(), mQuad2DIL(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, @@ -254,516 +592,552 @@ Blit11::Blit11(Renderer11 *renderer) 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) + mSwizzleCB(), + 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(), + mResolvedDepthStencilRTView() { } Blit11::~Blit11() { - freeResources(); - - mQuad2DIL.release(); - mQuad2DVS.release(); - mDepthPS.release(); - - mQuad3DIL.release(); - mQuad3DVS.release(); - mQuad3DGS.release(); - - clearShaderMap(); } gl::Error Blit11::initResources() { if (mResourcesInitialized) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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->getRendererCaps().max3DTextureSize); - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; + 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"); + ANGLE_TRY(mRenderer->allocateResource(vbDesc, &mVertexBuffer)); + mVertexBuffer.setDebugName("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.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; + 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"); + ANGLE_TRY(mRenderer->allocateResource(pointSamplerDesc, &mPointSampler)); + mPointSampler.setDebugName("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.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; + 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"); + ANGLE_TRY(mRenderer->allocateResource(linearSamplerDesc, &mLinearSampler)); + mLinearSampler.setDebugName("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.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.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"); + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorEnabledRasterizerState)); + mScissorEnabledRasterizerState.setDebugName("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"); + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorDisabledRasterizerState)); + mScissorDisabledRasterizerState.setDebugName("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.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"); + 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; + + ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mDepthStencilState)); + mDepthStencilState.setDebugName("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.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"); + ANGLE_TRY(mRenderer->allocateResource(swizzleBufferDesc, &mSwizzleCB)); + mSwizzleCB.setDebugName("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; + return gl::NoError(); } // static -Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension) +Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, + GLenum sourceFormat, + 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; + 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; + 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; + 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 { - switch (destinationFormat) + bool floatToIntBlit = + !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat); + if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit) { - 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; + switch (destinationFormat) + { + case GL_RGBA: + case GL_BGRA_EXT: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY + : BLITSHADER_2D_RGBAF_UNMULTIPLY; + + case GL_RGB: + case GL_RG: + case GL_RED: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY + : BLITSHADER_2D_RGBF_UNMULTIPLY; + + case GL_RGBA_INTEGER: + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha) + { + return BLITSHADER_2D_RGBAF_TOUI; + } + else + { + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY + : BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY; + } + + case GL_RGB_INTEGER: + case GL_RG_INTEGER: + case GL_RED_INTEGER: + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha) + { + return BLITSHADER_2D_RGBF_TOUI; + } + else + { + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY + : BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY; + } + case GL_LUMINANCE: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAF_PREMULTIPLY + : BLITSHADER_2D_LUMAF_UNMULTIPLY; + case GL_LUMINANCE_ALPHA: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY + : BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY; + case GL_ALPHA: + ASSERT(!floatToIntBlit); + return BLITSHADER_2D_ALPHA; + 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) +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: + 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; - } - default: - UNREACHABLE(); - return SWIZZLESHADER_INVALID; } } -Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader) +gl::Error Blit11::getShaderSupport(const Shader &shader, Blit11::ShaderSupport *supportOut) { - 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; + ANGLE_TRY(mQuad2DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad2DVS.resolve(mRenderer)); + supportOut->inputLayout = &mQuad2DIL.getObj(); + supportOut->vertexShader = &mQuad2DVS.getObj(); + supportOut->geometryShader = nullptr; + supportOut->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; + ANGLE_TRY(mQuad3DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad3DVS.resolve(mRenderer)); + ANGLE_TRY(mQuad3DGS.resolve(mRenderer)); + supportOut->inputLayout = &mQuad2DIL.getObj(); + supportOut->vertexShader = &mQuad3DVS.getObj(); + supportOut->geometryShader = &mQuad3DGS.getObj(); + supportOut->vertexWriteFunction = Write3DVertices; } - return support; + return gl::NoError(); } -gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, - ID3D11RenderTargetView *dest, +gl::Error Blit11::swizzleTexture(const gl::Context *context, + const d3d11::SharedSRV &source, + const d3d11::RenderTargetView &dest, const gl::Extents &size, - GLenum swizzleRed, - GLenum swizzleGreen, - GLenum swizzleBlue, - GLenum swizzleAlpha) + const gl::SwizzleState &swizzleTarget) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initResources()); HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; - source->GetDesc(&sourceSRVDesc); + source.get()->GetDesc(&sourceSRVDesc); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + 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 (sourceFormatInfo.componentType) + 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; + 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; - error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader)); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = + deviceContext->Map(mVertexBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for swizzle, " + << gl::FmtHR(result); } - const ShaderSupport &support = getShaderSupport(*shader); + ShaderSupport support; + ANGLE_TRY(getShaderSupport(*shader, &support)); - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 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); + support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, + &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); // Set constant buffer - result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = deviceContext->Map(mSwizzleCB.get(), 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); + return gl::OutOfMemory() << "Failed to map internal constant buffer for swizzle, " + << gl::FmtHR(result); } - unsigned int *swizzleIndices = reinterpret_cast<unsigned int*>(mappedResource.pData); - swizzleIndices[0] = GetSwizzleIndex(swizzleRed); - swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); - swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); - swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); + 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); + deviceContext->Unmap(mSwizzleCB.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply constant buffer - deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + stateManager->setPixelConstantBuffer(0, &mSwizzleCB); // Apply state - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setRasterizerState(&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); + stateManager->setInputLayout(support.inputLayout); + stateManager->setPrimitiveTopology(topology); - // Unset the currently bound shader resource to avoid conflicts - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + stateManager->setDrawShaders(support.vertexShader, support.geometryShader, + &shader->pixelShader); // Apply render target - mRenderer->setOneTimeRenderTarget(dest); + stateManager->setRenderTarget(dest.get(), 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); + stateManager->setSimpleViewport(size); - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); + // Apply textures and sampler + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); // Draw the quad deviceContext->Draw(drawCount, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, +gl::Error Blit11::copyTexture(const gl::Context *context, + const d3d11::SharedSRV &source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, + GLenum sourceFormat, + const d3d11::RenderTargetView &dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor, GLenum destFormat, GLenum filter, - bool maskOffAlpha) + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initResources()); HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -771,635 +1145,1009 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, // 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); + source.get()->GetDesc(&sourceSRVDesc); + + GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + ASSERT(componentType != GL_NONE); + ASSERT(componentType != GL_SIGNED_NORMALIZED); + bool isSigned = (componentType == GL_INT); - bool isSigned = (internalFormatInfo.componentType == GL_INT); - ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; + ShaderDimension dimension = + (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; const Shader *shader = nullptr; - error = getBlitShader(destFormat, isSigned, dimension, &shader); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getBlitShader(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha, dimension, &shader)); - const ShaderSupport &support = getShaderSupport(*shader); + ShaderSupport support; + ANGLE_TRY(getShaderSupport(*shader, &support)); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = + deviceContext->Map(mVertexBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, " + << gl::FmtHR(result); } - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, &drawCount, &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply state if (maskOffAlpha) { - ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice()); - ASSERT(blendState); - deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF); + ANGLE_TRY(mAlphaMaskBlendState.resolve(mRenderer)); + stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj()); } else { - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + stateManager->setSimpleBlendState(nullptr); } - deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setDepthStencilState(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); + stateManager->setSimpleScissorRect(*scissor); + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); } else { - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setRasterizerState(&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); + stateManager->setInputLayout(support.inputLayout); + stateManager->setPrimitiveTopology(topology); - // Unset the currently bound shader resource to avoid conflicts - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + stateManager->setDrawShaders(support.vertexShader, support.geometryShader, + &shader->pixelShader); // Apply render target - mRenderer->setOneTimeRenderTarget(dest); + stateManager->setRenderTarget(dest.get(), 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; + stateManager->setSimpleViewport(destSize); + + // Apply texture and sampler 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."); + case GL_NEAREST: + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); + break; + case GL_LINEAR: + stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler); + break; + + default: + UNREACHABLE(); + return gl::InternalError() << "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); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, +gl::Error Blit11::copyStencil(const gl::Context *context, + 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 copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, true); + 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, +gl::Error Blit11::copyDepth(const gl::Context *context, + const d3d11::SharedSRV &source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const d3d11::DepthStencilView &dest, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + 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); + result = + deviceContext->Map(mVertexBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, " + << gl::FmtHR(result); } - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; - Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, - &stride, &drawCount, &topology); + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, + &drawCount, &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply state - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(&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); + stateManager->setSimpleScissorRect(*scissor); + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); } else { - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setRasterizerState(&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"); - } + ANGLE_TRY(mQuad2DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad2DVS.resolve(mRenderer)); + ANGLE_TRY(mDepthPS.resolve(mRenderer)); // Apply shaders - deviceContext->IASetInputLayout(mQuad2DIL.resolve(device)); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(quad2DVS, nullptr, 0); + stateManager->setInputLayout(&mQuad2DIL.getObj()); + stateManager->setPrimitiveTopology(topology); - 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); + stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj()); // Apply render target - deviceContext->OMSetRenderTargets(0, nullptr, dest); + stateManager->setRenderTarget(nullptr, dest.get()); // 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); + stateManager->setSimpleViewport(destSize); - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); + // Apply texture and sampler + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); // Draw the quad deviceContext->Draw(drawCount, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, +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 copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, false); + return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, false); } -gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly) +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) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + 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; - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS); - ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); - // 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 - ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); + 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 (!sourceStaging || !destStaging) + if (srcDXGIFormat != destDXGIFormat) { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit."); + 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); } - DXGI_FORMAT format = GetTextureFormat(source); - ASSERT(format == GetTextureFormat(dest)); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource, + destArea, destSize, scissor, copyOffset, copyOffset, copySize, + srcPixelSize, destPixelSize, StretchedBlitNearest); +} - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - unsigned int pixelSize = dxgiFormatInfo.pixelBytes; - unsigned int copyOffset = 0; - unsigned int copySize = pixelSize; - if (stencilOnly) - { - copyOffset = dxgiFormatInfo.depthBits / 8; - copySize = dxgiFormatInfo.stencilBits / 8; +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()); - // It would be expensive to have non-byte sized stencil sizes since it would - // require reading from the destination, currently there aren't any though. - ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && - dxgiFormatInfo.depthBits % 8 == 0); - } + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + TextureHelper11 sourceStaging; + ANGLE_TRY_RESULT(mRenderer->createStagingTexture(ResourceType::Texture2D, source.getFormatSet(), + sourceSize, StagingAccess::READ), + sourceStaging); + + deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(), + sourceSubresource, nullptr); D3D11_MAPPED_SUBRESOURCE sourceMapping; - HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + HRESULT result = deviceContext->Map(sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping); if (FAILED(result)) { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result); + return gl::OutOfMemory() + << "Failed to map internal source staging texture for depth stencil blit, " + << gl::FmtHR(result); } D3D11_MAPPED_SUBRESOURCE destMapping; - result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + result = deviceContext->Map(destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping); if (FAILED(result)) { - deviceContext->Unmap(sourceStaging, 0); - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result); + deviceContext->Unmap(sourceStaging.get(), 0); + return gl::OutOfMemory() + << "Failed to map internal destination staging texture for depth stencil blit, " + << gl::FmtHR(result); } - gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); - // Clip dest area to the destination size - gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); + gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height); // Clip dest area to the scissor if (scissor) { - gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); + gl::ClipRectangle(clipRect, *scissor, &clipRect); } - // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is - // no out of bounds lookups required, the entire pixel is copied and no stretching - bool wholeRowCopy = sourceArea.width == clippedDestArea.width && - sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && - copySize == pixelSize; + 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)); - for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) - { - float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1); + deviceContext->Unmap(sourceStaging.get(), 0); + deviceContext->Unmap(destStaging.get(), 0); - // 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 * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1)); - unsigned int writeRow = y; - - if (wholeRowCopy) - { - void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - sourceArea.x * pixelSize; + return gl::NoError(); +} - void *destRow = reinterpret_cast<char*>(destMapping.pData) + - writeRow * destMapping.RowPitch + - destArea.x * pixelSize; +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()); - memcpy(destRow, sourceRow, pixelSize * destArea.width); - } - else - { - for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) - { - float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges - unsigned int readColumn = static_cast<unsigned int>(gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1)); - unsigned int writeColumn = x; + // 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(mRenderer->createStagingTexture(ResourceType::Texture2D, dest.getFormatSet(), + destSize, StagingAccess::READ_WRITE), + destStaging); - void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - readColumn * pixelSize + - copyOffset; + deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource, + nullptr); - void *destPixel = reinterpret_cast<char*>(destMapping.pData) + - writeRow * destMapping.RowPitch + - writeColumn * pixelSize + - copyOffset; + ANGLE_TRY(copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, + destArea, destSize, scissor, readOffset, writeOffset, copySize, + srcPixelStride, destPixelStride, convertFunction)); - memcpy(destPixel, sourcePixel, copySize); - } - } + // Work around timeouts/TDRs in older NVIDIA drivers. + if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy) + { + D3D11_MAPPED_SUBRESOURCE mapped; + deviceContext->Map(destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped); + deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData, + mapped.RowPitch, mapped.DepthPitch); + deviceContext->Unmap(destStaging.get(), 0); + } + else + { + deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0, + destStaging.get(), 0, nullptr); } - // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion - // according to MSDN. - deviceContext->UpdateSubresource(dest, destSubresource, nullptr, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); - - deviceContext->Unmap(sourceStaging, 0); - deviceContext->Unmap(destStaging, 0); - - // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some - // systems when called repeatedly. - // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, nullptr); - - SafeRelease(sourceStaging); - SafeRelease(destStaging); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) +gl::Error Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name) { ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end()); - ASSERT(ps); + + d3d11::PixelShader ps; + ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps)); + ps.setDebugName(name); Shader shader; - shader.dimension = dimension; - shader.pixelShader = ps; + shader.dimension = dimension; + shader.pixelShader = std::move(ps); - mBlitShaderMap[blitShaderType] = shader; + mBlitShaderMap[blitShaderType] = std::move(shader); + return gl::NoError(); } -void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) +gl::Error Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name) { ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end()); - ASSERT(ps); + + d3d11::PixelShader ps; + ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps)); + ps.setDebugName(name); Shader shader; - shader.dimension = dimension; - shader.pixelShader = ps; + shader.dimension = dimension; + shader.pixelShader = std::move(ps); - mSwizzleShaderMap[swizzleShaderType] = shader; + mSwizzleShaderMap[swizzleShaderType] = std::move(shader); + return gl::NoError(); } 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, ShaderDimension dimension, const Shader **shader) +gl::Error Blit11::getBlitShader(GLenum destFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shader) { - BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, dimension); + BlitShaderType blitShaderType = + GetBlitShaderType(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha, dimension); if (blitShaderType == BLITSHADER_INVALID) { - return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch"); + return gl::InternalError() << "Internal blit shader type mismatch"; } auto blitShaderIt = mBlitShaderMap.find(blitShaderType); if (blitShaderIt != mBlitShaderMap.end()) { *shader = &blitShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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_BGRAF: - addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA 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_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"); + case BLITSHADER_2D_RGBAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2D), + "Blit11 2D RGBA pixel shader")); + break; + case BLITSHADER_2D_BGRAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2D), + "Blit11 2D BGRA pixel shader")); + break; + case BLITSHADER_2D_RGBF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2D), + "Blit11 2D RGB pixel shader")); + break; + case BLITSHADER_2D_RGF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2D), + "Blit11 2D RG pixel shader")); + break; + case BLITSHADER_2D_RF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughR2D), + "Blit11 2D R pixel shader")); + break; + case BLITSHADER_2D_ALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughA2D), + "Blit11 2D alpha pixel shader")); + break; + case BLITSHADER_2D_LUMA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughLum2D), + "Blit11 2D lum pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughLumAlpha2D), + "Blit11 2D luminance alpha pixel shader")); + break; + case BLITSHADER_2D_RGBAUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2DUI), + "Blit11 2D RGBA UI pixel shader")); + break; + case BLITSHADER_2D_RGBAI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2DI), + "Blit11 2D RGBA I pixel shader")); + break; + case BLITSHADER_2D_RGBUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2DUI), + "Blit11 2D RGB UI pixel shader")); + break; + case BLITSHADER_2D_RGBI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2DI), + "Blit11 2D RGB I pixel shader")); + break; + case BLITSHADER_2D_RGUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2DUI), + "Blit11 2D RG UI pixel shader")); + break; + case BLITSHADER_2D_RGI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2DI), + "Blit11 2D RG I pixel shader")); + break; + case BLITSHADER_2D_RUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughR2DUI), + "Blit11 2D R UI pixel shader")); + break; + case BLITSHADER_2D_RI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughR2DI), + "Blit11 2D R I pixel shader")); + break; + case BLITSHADER_3D_RGBAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3DUI), + "Blit11 3D UI RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3DI), + "Blit11 3D I RGBA pixel shader")); + break; + case BLITSHADER_3D_BGRAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D BGRA pixel shader")); + break; + case BLITSHADER_3D_RGBF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3D), + "Blit11 3D RGB pixel shader")); + break; + case BLITSHADER_3D_RGBUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3DUI), + "Blit11 3D RGB UI pixel shader")); + break; + case BLITSHADER_3D_RGBI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3DI), + "Blit11 3D RGB I pixel shader")); + break; + case BLITSHADER_3D_RGF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3D), + "Blit11 3D RG pixel shader")); + break; + case BLITSHADER_3D_RGUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3DUI), + "Blit11 3D RG UI pixel shader")); + break; + case BLITSHADER_3D_RGI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3DI), + "Blit11 3D RG I pixel shader")); + break; + case BLITSHADER_3D_RF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, ShaderData(g_PS_PassthroughR3D), + "Blit11 3D R pixel shader")); + break; + case BLITSHADER_3D_RUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughR3DUI), + "Blit11 3D R UI pixel shader")); + break; + case BLITSHADER_3D_RI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughR3DI), + "Blit11 3D R I pixel shader")); + break; + case BLITSHADER_3D_ALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D alpha pixel shader")); + break; + case BLITSHADER_3D_LUMA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughLum3D), + "Blit11 3D luminance pixel shader")); + break; + case BLITSHADER_3D_LUMAALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughLumAlpha3D), + "Blit11 3D luminance alpha pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGBA), + "Blit11 2D RGBA premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGBA), + "Blit11 2D RGBA unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGB), + "Blit11 2D RGB premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGB), + "Blit11 2D RGB unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGBA), + "Blit11 2D RGBA to uint pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGBA), + "Blit11 2D RGBA to uint premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGBA), + "Blit11 2D RGBA to uint unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGB), + "Blit11 2D RGB to uint pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGB), + "Blit11 2D RGB to uint premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGB), + "Blit11 2D RGB to uint unmultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_LUMA), + "Blit11 2D LUMA premultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_LUMA), + "Blit11 2D LUMA unmultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_FtoF_PM_LUMAALPHA), + "Blit11 2D LUMAALPHA premultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_FtoF_UM_LUMAALPHA), + "Blit11 2D LUMAALPHA unmultiply pixel shader")); + break; + + default: + UNREACHABLE(); + return gl::InternalError() << "Internal error"; } blitShaderIt = mBlitShaderMap.find(blitShaderType); ASSERT(blitShaderIt != mBlitShaderMap.end()); *shader = &blitShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shader) +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"); + return gl::InternalError() << "Swizzle shader type not found"; } auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); if (swizzleShaderIt != mSwizzleShaderMap.end()) { *shader = &swizzleShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // 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"); + case SWIZZLESHADER_2D_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleF2D), + "Blit11 2D F swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleUI2D), + "Blit11 2D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleI2D), + "Blit11 2D I swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF2DArray), + "Blit11 2D Cube F swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI2DArray), + "Blit11 2D Cube UI swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI2DArray), + "Blit11 2D Cube I swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF3D), + "Blit11 3D F swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI3D), + "Blit11 3D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI3D), + "Blit11 3D I swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF2DArray), + "Blit11 2D Array F swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI2DArray), + "Blit11 2D Array UI swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI2DArray), + "Blit11 2D Array I swizzle pixel shader")); + break; + default: + UNREACHABLE(); + return gl::InternalError() << "Internal error"; } swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); ASSERT(swizzleShaderIt != mSwizzleShaderMap.end()); *shader = &swizzleShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } +gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(const gl::Context *context, + RenderTarget11 *depth) +{ + ANGLE_TRY(initResources()); + + // Multisampled depth stencil SRVs are not available in feature level 10.0 + ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0); + + const auto &extents = depth->getExtents(); + auto *deviceContext = mRenderer->getDeviceContext(); + auto *stateManager = mRenderer->getStateManager(); + + ANGLE_TRY(initResolveDepthOnly(depth->getFormatSet(), extents)); + + ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer)); + ANGLE_TRY(mResolveDepthPS.resolve(mRenderer)); + + // Apply the necessary state changes to the D3D11 immediate device context. + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, + &mResolveDepthPS.getObj()); + stateManager->setRasterizerState(nullptr); + stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF); + stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get()); + stateManager->setSimpleBlendState(nullptr); + stateManager->setSimpleViewport(extents); + + // Set the viewport + stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0, &depth->getShaderResourceView()); + + // Trigger the blit on the GPU. + deviceContext->Draw(6, 0); + + return mResolvedDepth; } + +gl::Error Blit11::initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents) +{ + if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() && + format.texFormat == mResolvedDepth.getFormat()) + { + return gl::NoError(); + } + + D3D11_TEXTURE2D_DESC textureDesc; + textureDesc.Width = extents.width; + textureDesc.Height = extents.height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = format.texFormat; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateTexture(textureDesc, format, &mResolvedDepth)); + mResolvedDepth.setDebugName("Blit11::mResolvedDepth"); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Flags = 0; + dsvDesc.Format = format.dsvFormat; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, mResolvedDepth.get(), &mResolvedDepthDSView)); + mResolvedDepthDSView.setDebugName("Blit11::mResolvedDepthDSView"); + + // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render + // works as expected. Otherwise the results of the first use seem to be incorrect. + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0); + + return gl::NoError(); +} + +gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents) +{ + // Check if we need to recreate depth stencil view + if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents()) + { + ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT); + 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; + + ANGLE_TRY(mRenderer->allocateTexture(textureDesc, formatSet, &mResolvedDepthStencil)); + mResolvedDepthStencil.setDebugName("Blit11::mResolvedDepthStencil"); + + ANGLE_TRY(mRenderer->allocateResourceNoDesc(mResolvedDepthStencil.get(), + &mResolvedDepthStencilRTView)); + mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView"); + + return gl::NoError(); +} + +gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(const gl::Context *context, + RenderTarget11 *depthStencil, + bool alsoDepth) +{ + ANGLE_TRY(initResources()); + + // Multisampled depth stencil SRVs are not available in feature level 10.0 + ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0); + + const auto &extents = depthStencil->getExtents(); + + ANGLE_TRY(initResolveDepthStencil(extents)); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto *stateManager = mRenderer->getStateManager(); + ID3D11Resource *stencilResource = depthStencil->getTexture().get(); + + // Check if we need to re-create the stencil SRV. + if (mStencilSRV.valid()) + { + ID3D11Resource *priorResource = nullptr; + mStencilSRV.get()->GetResource(&priorResource); + + if (stencilResource != priorResource) + { + mStencilSRV.reset(); + } + + SafeRelease(priorResource); + } + + if (!mStencilSRV.valid()) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc; + srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet()); + srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + + ANGLE_TRY(mRenderer->allocateResource(srViewDesc, stencilResource, &mStencilSRV)); + mStencilSRV.setDebugName("Blit11::mStencilSRV"); + } + + // Notify the Renderer that all state should be invalidated. + ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer)); + + // 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. + const d3d11::PixelShader *pixelShader = nullptr; + if (alsoDepth) + { + ANGLE_TRY(mResolveDepthStencilPS.resolve(mRenderer)); + pixelShader = &mResolveDepthStencilPS.getObj(); + } + else + { + ANGLE_TRY(mResolveStencilPS.resolve(mRenderer)); + pixelShader = &mResolveStencilPS.getObj(); + } + + // Apply the necessary state changes to the D3D11 immediate device context. + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader); + stateManager->setRasterizerState(nullptr); + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr); + stateManager->setSimpleBlendState(nullptr); + + // Set the viewport + stateManager->setSimpleViewport(extents); + stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0, + &depthStencil->getShaderResourceView()); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 1, &mStencilSRV); + + // Trigger the blit on the GPU. + deviceContext->Draw(6, 0); + + gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1); + + TextureHelper11 dest; + ANGLE_TRY_RESULT( + mRenderer->createStagingTexture(ResourceType::Texture2D, depthStencil->getFormatSet(), + extents, StagingAccess::READ_WRITE), + 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() +{ + mStencilSRV.reset(); + mResolvedDepthStencilRTView.reset(); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h index 906616131e..14078f9db8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -10,8 +10,9 @@ #define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ #include "common/angleutils.h" -#include "libANGLE/angletypes.h" #include "libANGLE/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include <map> @@ -26,36 +27,84 @@ class Blit11 : angle::NonCopyable explicit Blit11(Renderer11 *renderer); ~Blit11(); - gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + gl::Error swizzleTexture(const gl::Context *context, + const d3d11::SharedSRV &source, + const d3d11::RenderTargetView &dest, + const gl::Extents &size, + const gl::SwizzleState &swizzleTarget); - gl::Error copyTexture(ID3D11ShaderResourceView *source, + gl::Error copyTexture(const gl::Context *context, + const d3d11::SharedSRV &source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, + GLenum sourceFormat, + const d3d11::RenderTargetView &dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor, GLenum destFormat, GLenum filter, - bool maskOffAlpha); + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha); - gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + gl::Error copyStencil(const gl::Context *context, + 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, + gl::Error copyDepth(const gl::Context *context, + const d3d11::SharedSRV &source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const d3d11::DepthStencilView &dest, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor); - gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + 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(const gl::Context *context, + RenderTarget11 *depth); + + gl::ErrorOrResult<TextureHelper11> resolveStencil(const gl::Context *context, + 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, + + // Passthrough shaders BLITSHADER_2D_RGBAF, BLITSHADER_2D_BGRAF, BLITSHADER_2D_RGBF, @@ -88,6 +137,27 @@ class Blit11 : angle::NonCopyable BLITSHADER_3D_ALPHA, BLITSHADER_3D_LUMA, BLITSHADER_3D_LUMAALPHA, + + // Multiply alpha shaders + BLITSHADER_2D_RGBAF_PREMULTIPLY, + BLITSHADER_2D_RGBAF_UNMULTIPLY, + + BLITSHADER_2D_RGBF_PREMULTIPLY, + BLITSHADER_2D_RGBF_UNMULTIPLY, + + BLITSHADER_2D_RGBAF_TOUI, + BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY, + BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY, + + BLITSHADER_2D_RGBF_TOUI, + BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY, + BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY, + + BLITSHADER_2D_LUMAF_PREMULTIPLY, + BLITSHADER_2D_LUMAF_UNMULTIPLY, + + BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY, + BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY }; enum SwizzleShaderType @@ -107,9 +177,13 @@ class Blit11 : angle::NonCopyable 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, + 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 @@ -120,38 +194,102 @@ class Blit11 : angle::NonCopyable struct Shader { + Shader(); + Shader(Shader &&other); + ~Shader(); + Shader &operator=(Shader &&other); + ShaderDimension dimension; - ID3D11PixelShader *pixelShader; + d3d11::PixelShader pixelShader; }; struct ShaderSupport { - ID3D11InputLayout *inputLayout; - ID3D11VertexShader *vertexShader; - ID3D11GeometryShader *geometryShader; + const d3d11::InputLayout *inputLayout; + const d3d11::VertexShader *vertexShader; + const d3d11::GeometryShader *geometryShader; WriteVertexFunction vertexWriteFunction; }; gl::Error initResources(); - void freeResources(); - ShaderSupport getShaderSupport(const Shader &shader); + gl::Error getShaderSupport(const Shader &shader, ShaderSupport *supportOut); - static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension); + static BlitShaderType GetBlitShaderType(GLenum destinationFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension); static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality); - gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly); - - void addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps); - - gl::Error getBlitShader(GLenum destFormat, bool isSigned, 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); + 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); + + gl::Error addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name); + + gl::Error getBlitShader(GLenum destFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shaderOut); + gl::Error getSwizzleShader(GLenum type, + D3D11_SRV_DIMENSION viewDimension, + const Shader **shaderOut); + + gl::Error addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name); void clearShaderMap(); + void releaseResolveDepthStencilResources(); + gl::Error initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents); + gl::Error initResolveDepthStencil(const gl::Extents &extents); Renderer11 *mRenderer; @@ -159,12 +297,12 @@ class Blit11 : angle::NonCopyable std::map<SwizzleShaderType, Shader> mSwizzleShaderMap; bool mResourcesInitialized; - ID3D11Buffer *mVertexBuffer; - ID3D11SamplerState *mPointSampler; - ID3D11SamplerState *mLinearSampler; - ID3D11RasterizerState *mScissorEnabledRasterizerState; - ID3D11RasterizerState *mScissorDisabledRasterizerState; - ID3D11DepthStencilState *mDepthStencilState; + d3d11::Buffer mVertexBuffer; + d3d11::SamplerState mPointSampler; + d3d11::SamplerState mLinearSampler; + d3d11::RasterizerState mScissorEnabledRasterizerState; + d3d11::RasterizerState mScissorDisabledRasterizerState; + d3d11::DepthStencilState mDepthStencilState; d3d11::LazyInputLayout mQuad2DIL; d3d11::LazyShader<ID3D11VertexShader> mQuad2DVS; @@ -176,9 +314,19 @@ class Blit11 : angle::NonCopyable d3d11::LazyBlendState mAlphaMaskBlendState; - ID3D11Buffer *mSwizzleCB; + d3d11::Buffer mSwizzleCB; + + d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS; + d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS; + d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS; + d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS; + d3d11::ShaderResourceView mStencilSRV; + TextureHelper11 mResolvedDepthStencil; + d3d11::RenderTargetView mResolvedDepthStencilRTView; + TextureHelper11 mResolvedDepth; + d3d11::DepthStencilView mResolvedDepthDSView; }; -} +} // namespace rx -#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index 0d5dc08b03..2317c9abdb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -13,10 +13,14 @@ #include "common/MemoryBuffer.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/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/renderer_utils.h" + +namespace rx +{ namespace { @@ -27,41 +31,41 @@ 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); -} - -#if defined(ANGLE_MINGW32_COMPAT) -typedef enum D3D11_MAP_FLAG { - D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 -} D3D11_MAP_FLAG; -#endif -namespace rx -{ -PackPixelsParams::PackPixelsParams() - : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0) +enum class CopyResult { -} + RECREATED, + NOT_RECREATED, +}; -PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, - GLenum formatIn, - GLenum typeIn, - GLuint outputPitchIn, - const gl::PixelPackState &packIn, - ptrdiff_t offsetIn) - : area(areaIn), - format(formatIn), - type(typeIn), - outputPitch(outputPitchIn), - packBuffer(packIn.pixelBuffer.get()), - pack(packIn.alignment, packIn.reverseRowOrder), - offset(offsetIn) +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(GLbitfield access) +D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access) { bool readBit = ((access & GL_MAP_READ_BIT) != 0); bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); @@ -77,7 +81,8 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) } else if (writeBit && !readBit) { - return D3D11_MAP_WRITE; + // 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) { @@ -89,7 +94,7 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) 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 @@ -106,16 +111,22 @@ class Buffer11::BufferStorage : angle::NonCopyable size_t getSize() const { return mBufferSize; } void setDataRevision(DataRevision rev) { mRevision = rev; } - virtual bool isMappable() const = 0; + virtual bool isCPUAccessible(GLbitfield access) const = 0; + + virtual bool isGPUAccessible() const = 0; - virtual bool 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::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) = 0; + virtual gl::Error resize(const gl::Context *context, size_t size, bool preserveData) = 0; - virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; - virtual void unmap() = 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); @@ -133,28 +144,41 @@ class Buffer11::BufferStorage : angle::NonCopyable class Buffer11::NativeStorage : public Buffer11::BufferStorage { public: - NativeStorage(Renderer11 *renderer, BufferUsage usage); + NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const OnBufferDataDirtyChannel *onStorageChanged); ~NativeStorage() override; - bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } + bool isCPUAccessible(GLbitfield access) const override; + + bool isGPUAccessible() const override { return true; } - ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + const d3d11::Buffer &getBuffer() const { return mBuffer; } + gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; void unmap() override; + gl::ErrorOrResult<const d3d11::ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat); + private: - static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + void clearSRVs(); - ID3D11Buffer *mNativeStorage; + d3d11::Buffer mBuffer; + const OnBufferDataDirtyChannel *mOnStorageChanged; + std::map<DXGI_FORMAT, d3d11::ShaderResourceView> mBufferResourceViews; }; // A emulated indexed buffer storage represents an underlying D3D11 buffer for data @@ -166,28 +190,32 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage EmulatedIndexedStorage(Renderer11 *renderer); ~EmulatedIndexedStorage() override; - bool isMappable() const override { return true; } + bool isCPUAccessible(GLbitfield access) const override { return true; } + + bool isGPUAccessible() const override { return false; } - ID3D11Buffer *getNativeStorage(); + gl::ErrorOrResult<const d3d11::Buffer *> getBuffer(SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; + gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; void unmap() override; - bool update(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); private: - ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D - MemoryBuffer mMemoryBuffer; // original data (not expanded) - MemoryBuffer mIndicesMemoryBuffer; // indices data - SourceIndexData mIndexInfo; // indices information - size_t mAttributeStride; // per element stride in bytes - size_t mAttributeOffset; // starting offset + d3d11::Buffer mBuffer; // contains expanded data for use by D3D + angle::MemoryBuffer mMemoryBuffer; // original data (not expanded) + angle::MemoryBuffer mIndicesMemoryBuffer; // indices data }; // Pack storage represents internal storage for pack buffers. We implement pack buffers @@ -198,24 +226,32 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage explicit PackStorage(Renderer11 *renderer); ~PackStorage() override; - bool isMappable() const override { return true; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + bool isCPUAccessible(GLbitfield access) const override { return true; } - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + bool isGPUAccessible() const override { return false; } + + gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, 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, + gl::Error packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms); private: gl::Error flushQueuedPackCommand(); TextureHelper11 mStagingTexture; - MemoryBuffer mMemoryBuffer; + angle::MemoryBuffer mMemoryBuffer; std::unique_ptr<PackPixelsParams> mQueuedPackCommand; PackPixelsParams mPackParams; bool mDataModified; @@ -230,37 +266,46 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage explicit SystemMemoryStorage(Renderer11 *renderer); ~SystemMemoryStorage() override {} - bool isMappable() const override { return true; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + bool isCPUAccessible(GLbitfield access) const override { return true; } + + bool isGPUAccessible() const override { return false; } - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, 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; } + angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; } protected: - MemoryBuffer mSystemCopy; + angle::MemoryBuffer mSystemCopy; }; -Buffer11::Buffer11(Renderer11 *renderer) - : BufferD3D(renderer), +Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer) + : BufferD3D(state, renderer), mRenderer(renderer), mSize(0), mMappedStorage(nullptr), - mBufferStorages(BUFFER_USAGE_COUNT, nullptr), + mBufferStorages({}), + mLatestBufferStorage(nullptr), + mDeallocThresholds({}), + mIdleness({}), mConstantBufferStorageAdditionalSize(0), - mMaxConstantBufferLruCount(0), - mReadUsageCount(0) + mMaxConstantBufferLruCount(0) { } Buffer11::~Buffer11() { - for (auto &storage : mBufferStorages) + for (BufferStorage *&storage : mBufferStorages) { SafeDelete(storage); } @@ -273,79 +318,74 @@ Buffer11::~Buffer11() mRenderer->onBufferDelete(this); } -gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) +gl::Error Buffer11::setData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + gl::BufferUsage usage) { - gl::Error error = setSubData(data, size, 0); - if (error.isError()) - { - return error; - } - - updateD3DBufferUsage(usage); - return error; + updateD3DBufferUsage(context, usage); + ANGLE_TRY(setSubData(context, target, data, size, 0)); + return gl::NoError(); } -gl::Error Buffer11::getData(const uint8_t **outData) +gl::Error Buffer11::getData(const gl::Context *context, const uint8_t **outData) { SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); - - if (error.isError()) - { - *outData = nullptr; - return error; - } - - mReadUsageCount = 0; + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), systemMemoryStorage); ASSERT(systemMemoryStorage->getSize() >= mSize); *outData = systemMemoryStorage->getSystemCopy()->data(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut) +gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStorage( + const gl::Context *context) { - BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY); - - if (memStorageUntyped == nullptr) - { - // TODO(jmadill): convert all to errors - return gl::Error(GL_OUT_OF_MEMORY); - } - - *storageOut = GetAs<SystemMemoryStorage>(memStorageUntyped); - return gl::Error(GL_NO_ERROR); + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY), storage); + return GetAs<SystemMemoryStorage>(storage); } -gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) +gl::Error Buffer11::setSubData(const gl::Context *context, + gl::BufferBinding 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 (supportsDirectBinding()) + if (target == gl::BufferBinding::Uniform) { - writeBuffer = getStagingStorage(); - - if (!writeBuffer) + // 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(context, BUFFER_USAGE_UNIFORM), writeBuffer); + } + else { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer); } } + else if (supportsDirectBinding()) + { + ANGLE_TRY_RESULT(getStagingStorage(context), writeBuffer); + } else { - SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); - if (error.isError()) - { - return error; - } - - writeBuffer = systemMemoryStorage; + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer); } ASSERT(writeBuffer); @@ -355,24 +395,25 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) if (writeBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); - gl::Error error = writeBuffer->resize(requiredSize, preserveData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData)); } - writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size); - writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1); + ANGLE_TRY(writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size)); + onStorageUpdate(writeBuffer); + + // Notify any vertex arrays that we have dirty data. + // TODO(jmadill): Use a more fine grained notification for data updates. + mDirectBroadcastChannel.signal(context); } mSize = std::max(mSize, requiredSize); - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::copySubData(BufferImpl *source, +gl::Error Buffer11::copySubData(const gl::Context *context, + BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) @@ -380,28 +421,32 @@ gl::Error Buffer11::copySubData(BufferImpl *source, Buffer11 *sourceBuffer = GetAs<Buffer11>(source); ASSERT(sourceBuffer != nullptr); - BufferStorage *copyDest = getLatestBufferStorage(); + BufferStorage *copyDest = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), copyDest); + if (!copyDest) { - copyDest = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copyDest); } - BufferStorage *copySource = sourceBuffer->getLatestBufferStorage(); + BufferStorage *copySource = nullptr; + ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(context), copySource); - if (!copySource || !copyDest) + if (!copySource) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); + ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource); } - // 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()) + ASSERT(copySource && copyDest); + + // A staging buffer is needed if there is no cpu-cpu or gpu-gpu copy path avaiable. + if (!copyDest->isGPUAccessible() && !copySource->isCPUAccessible(GL_MAP_READ_BIT)) { - copySource = sourceBuffer->getStagingStorage(); + ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource); } - else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable()) + else if (!copySource->isGPUAccessible() && !copyDest->isCPUAccessible(GL_MAP_WRITE_BIT)) { - copyDest = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copyDest); } // D3D11 does not allow overlapped copies until 11.1, and only if the @@ -411,36 +456,48 @@ gl::Error Buffer11::copySubData(BufferImpl *source, { if (copySource->getUsage() == BUFFER_USAGE_STAGING) { - copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + copySource); } else { - copySource = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copySource); } } - copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset); - copyDest->setDataRevision(copyDest->getDataRevision() + 1); + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset), + copyResult); + onStorageUpdate(copyDest); mSize = std::max<size_t>(mSize, destOffset + size); - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); + + // Also notify that direct buffers are dirty. + mDirectBroadcastChannel.signal(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr) +gl::Error Buffer11::map(const gl::Context *context, GLenum access, void **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); + return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr); } -gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer11::mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) { ASSERT(!mMappedStorage); - BufferStorage *latestStorage = getLatestBufferStorage(); + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage); + if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || latestStorage->getUsage() == BUFFER_USAGE_STAGING)) { @@ -449,34 +506,32 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL } else { - // Fall back to using the staging buffer if the latest storage does - // not exist or is not CPU-accessible. - mMappedStorage = getStagingStorage(); + // Fall back to using the staging buffer if the latest storage does not exist or is not + // CPU-accessible. + ANGLE_TRY_RESULT(getStagingStorage(context), mMappedStorage); } if (!mMappedStorage) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); + return gl::OutOfMemory() << "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(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + onStorageUpdate(mMappedStorage); + invalidateStaticData(context); } - uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); - if (!mappedBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); - } + uint8_t *mappedBuffer = nullptr; + ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer)); + ASSERT(mappedBuffer); - *mapPtr = static_cast<GLvoid *>(mappedBuffer); - return gl::Error(GL_NO_ERROR); + *mapPtr = static_cast<void *>(mappedBuffer); + return gl::NoError(); } -gl::Error Buffer11::unmap(GLboolean *result) +gl::Error Buffer11::unmap(const gl::Context *context, GLboolean *result) { ASSERT(mMappedStorage); mMappedStorage->unmap(); @@ -485,168 +540,171 @@ gl::Error Buffer11::unmap(GLboolean *result) // TODO: detect if we had corruption. if so, return false. *result = GL_TRUE; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Buffer11::markTransformFeedbackUsage() +gl::Error Buffer11::markTransformFeedbackUsage(const gl::Context *context) { - BufferStorage *transformFeedbackStorage = - getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + BufferStorage *transformFeedbackStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + transformFeedbackStorage); if (transformFeedbackStorage) { - transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + onStorageUpdate(transformFeedbackStorage); } - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); + return gl::NoError(); } -void Buffer11::markBufferUsage() +void Buffer11::updateDeallocThreshold(BufferUsage usage) { - mReadUsageCount++; + // 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 system memory storage if we decide it isn't being used very often. - const unsigned int usageLimit = 5; +// Free the storage if we decide it isn't being used very often. +gl::Error Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage) +{ + mIdleness[usage]++; - BufferStorage *&sysMemUsage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; - if (mReadUsageCount > usageLimit && sysMemUsage != nullptr) + BufferStorage *&storage = mBufferStorages[usage]; + if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage]) { - if (getLatestBufferStorage() != sysMemUsage) + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage); + if (latestStorage != storage) { - SafeDelete(sysMemUsage); + SafeDelete(storage); } } + + return gl::NoError(); } -ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) +// Keep system memory when we are using it for the canonical version of data. +bool Buffer11::canDeallocateSystemMemory() const { - markBufferUsage(); - - BufferStorage *bufferStorage = getBufferStorage(usage); - - if (!bufferStorage) + // Must keep system memory on Intel. + if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers) { - // Storage out-of-memory - return nullptr; + return false; } - return GetAs<NativeStorage>(bufferStorage)->getNativeStorage(); + return (!mBufferStorages[BUFFER_USAGE_UNIFORM] || + mSize <= mRenderer->getNativeCaps().maxUniformBlockSize); } -ID3D11Buffer *Buffer11::getEmulatedIndexedBuffer(SourceIndexData *indexInfo, - const TranslatedAttribute *attribute) +void Buffer11::markBufferUsage(BufferUsage usage) { - markBufferUsage(); - - assert(indexInfo != nullptr); - assert(attribute != nullptr); + mIdleness[usage] = 0; +} - BufferStorage *bufferStorage = getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX); - if (!bufferStorage) +gl::Error Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage) +{ + if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory()) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY)); } - EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(bufferStorage); - if (!emulatedStorage->update(indexInfo, attribute)) + if (currentUsage != BUFFER_USAGE_STAGING) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING)); } - return emulatedStorage->getNativeStorage(); + return gl::NoError(); } -ID3D11Buffer *Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size) +gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(const gl::Context *context, BufferUsage usage) { - markBufferUsage(); + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, usage), storage); + return GetAs<NativeStorage>(storage)->getBuffer().get(); +} - BufferStorage *bufferStorage; +gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer( + const gl::Context *context, + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) +{ + ASSERT(indexInfo); - if (offset == 0) - { - bufferStorage = getBufferStorage(BUFFER_USAGE_UNIFORM); - } - else - { - bufferStorage = getConstantBufferRangeStorage(offset, size); - } + BufferStorage *untypedStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), + untypedStorage); - if (!bufferStorage) - { - // Storage out-of-memory - return nullptr; - } + EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage); + + const d3d11::Buffer *nativeStorage = nullptr; + ANGLE_TRY_RESULT(emulatedStorage->getBuffer(indexInfo, attribute, startVertex), nativeStorage); - return GetAs<NativeStorage>(bufferStorage)->getNativeStorage(); + return nativeStorage->get(); } -ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) +gl::Error Buffer11::getConstantBufferRange(const gl::Context *context, + GLintptr offset, + GLsizeiptr size, + const d3d11::Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut) { - BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + BufferStorage *bufferStorage = nullptr; - if (!storage) + if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_UNIFORM), bufferStorage); + CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut); } - - ID3D11Buffer *buffer = GetAs<NativeStorage>(storage)->getNativeStorage(); - - auto bufferSRVIt = mBufferResourceViews.find(srvFormat); - - if (bufferSRVIt != mBufferResourceViews.end()) + else { - if (bufferSRVIt->second.first == buffer) - { - return bufferSRVIt->second.second; - } - else - { - // The underlying buffer has changed since the SRV was created: recreate the SRV. - SafeRelease(bufferSRVIt->second.second); - } + ANGLE_TRY_RESULT(getConstantBufferRangeStorage(context, offset, size), bufferStorage); + *firstConstantOut = 0; + *numConstantsOut = 0; } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11ShaderResourceView *bufferSRV = nullptr; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); + *bufferOut = &GetAs<NativeStorage>(bufferStorage)->getBuffer(); - D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; - bufferSRVDesc.Buffer.ElementOffset = 0; - bufferSRVDesc.Buffer.ElementWidth = - static_cast<unsigned int>(mSize) / dxgiFormatInfo.pixelBytes; - bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - bufferSRVDesc.Format = srvFormat; - - HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); + return gl::NoError(); +} - return bufferSRV; +gl::ErrorOrResult<const d3d11::ShaderResourceView *> Buffer11::getSRV(const gl::Context *context, + DXGI_FORMAT srvFormat) +{ + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK), storage); + NativeStorage *nativeStorage = GetAs<NativeStorage>(storage); + return nativeStorage->getSRVForFormat(srvFormat); } -gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, +gl::Error Buffer11::packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms) { - PackStorage *packStorage = getPackStorage(); - BufferStorage *latestStorage = getLatestBufferStorage(); + PackStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getPackStorage(context), packStorage); - if (packStorage) - { - gl::Error error = packStorage->packPixels(readAttachment, params); - if (error.isError()) - { - return error; - } - packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); - } + ASSERT(packStorage); + ANGLE_TRY(packStorage->packPixels(context, readAttachment, params)); + onStorageUpdate(packStorage); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } size_t Buffer11::getTotalCPUBufferMemoryBytes() const @@ -662,48 +720,56 @@ size_t Buffer11::getTotalCPUBufferMemoryBytes() const return allocationSize; } -Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) +gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(const gl::Context *context, + BufferUsage usage) { ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); BufferStorage *&newStorage = mBufferStorages[usage]; if (!newStorage) { - if (usage == BUFFER_USAGE_PIXEL_PACK) - { - newStorage = new PackStorage(mRenderer); - } - else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) - { - newStorage = new SystemMemoryStorage(mRenderer); - } - else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX) - { - newStorage = new EmulatedIndexedStorage(mRenderer); - } - else - { - // buffer is not allocated, create it - newStorage = new NativeStorage(mRenderer, usage); - } + newStorage = allocateStorage(usage); } + markBufferUsage(usage); + // resize buffer if (newStorage->getSize() < mSize) { - if (newStorage->resize(mSize, true).isError()) - { - // Out of memory error - return nullptr; - } + ANGLE_TRY(newStorage->resize(context, mSize, true)); } - updateBufferStorage(newStorage, 0, mSize); + ASSERT(newStorage); + + ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize)); + ANGLE_TRY(garbageCollection(context, usage)); return newStorage; } -Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size) +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_INDEX: + 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( + const gl::Context *context, + GLintptr offset, + GLsizeiptr size) { BufferStorage *newStorage; @@ -714,7 +780,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset if (!cacheEntry->storage) { - cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM); + cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM); cacheEntry->lruCount = ++mMaxConstantBufferLruCount; } @@ -722,6 +788,8 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset newStorage = cacheEntry->storage; } + markBufferUsage(BUFFER_USAGE_UNIFORM); + if (newStorage->getSize() < static_cast<size_t>(size)) { size_t maximumAllowedAdditionalSize = 2 * getSize(); @@ -733,8 +801,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache), std::end(mConstantBufferRangeStoragesCache), [](const ConstantBufferCache::value_type &a, - const ConstantBufferCache::value_type &b) - { + const ConstantBufferCache::value_type &b) { return a.second.lruCount < b.second.lruCount; }); @@ -746,12 +813,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset mConstantBufferRangeStoragesCache.erase(iter); } - if (newStorage->resize(size, false).isError()) - { - // Out of memory error - return nullptr; - } - + ANGLE_TRY(newStorage->resize(context, size, false)); mConstantBufferStorageAdditionalSize += sizeDelta; // We don't copy the old data when resizing the constant buffer because the data may be @@ -760,103 +822,148 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset newStorage->setDataRevision(0); } - updateBufferStorage(newStorage, offset, size); - + ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size)); + ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM)); return newStorage; } -void Buffer11::updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize) +gl::Error Buffer11::updateBufferStorage(const gl::Context *context, + BufferStorage *storage, + size_t sourceOffset, + size_t storageSize) { - BufferStorage *latestBuffer = getLatestBufferStorage(); - 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() || !storage->isMappable())) - { - NativeStorage *stagingBuffer = getStagingStorage(); + BufferStorage *latestBuffer = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestBuffer); - stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); - stagingBuffer->setDataRevision(latestBuffer->getDataRevision()); - - latestBuffer = stagingBuffer; - } + ASSERT(storage); - // if copyFromStorage returns true, the D3D buffer has been recreated - // and we should update our serial - if (storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0)) - { - updateSerial(); - } - storage->setDataRevision(latestBuffer->getDataRevision()); + if (!latestBuffer) + { + onStorageUpdate(storage); + return gl::NoError(); } -} -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 (latestBuffer->getDataRevision() <= storage->getDataRevision()) { - if (storage && (!latestStorage || storage->getDataRevision() > latestRevision)) - { - latestStorage = storage; - latestRevision = storage->getDataRevision(); - } + return gl::NoError(); } - // resize buffer - if (latestStorage && latestStorage->getSize() < mSize) + // 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->isCPUAccessible(GL_MAP_READ_BIT) || + !storage->isCPUAccessible(GL_MAP_WRITE_BIT))) { - if (latestStorage->resize(mSize, true).isError()) - { - // Out of memory error - return nullptr; - } + NativeStorage *stagingBuffer = nullptr; + ANGLE_TRY_RESULT(getStagingStorage(context), stagingBuffer); + + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT( + stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(), 0), + copyResult); + onCopyStorage(stagingBuffer, latestBuffer); + + latestBuffer = stagingBuffer; } - return latestStorage; + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0), + copyResult); + // If the D3D buffer has been recreated, we should update our serial. + if (copyResult == CopyResult::RECREATED) + { + updateSerial(); + } + onCopyStorage(storage, latestBuffer); + return gl::NoError(); } -Buffer11::NativeStorage *Buffer11::getStagingStorage() +gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getLatestBufferStorage( + const gl::Context *context) const { - BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); - - if (!stagingStorage) + // resize buffer + if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize) { - // Out-of-memory - return nullptr; + ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true)); } - return GetAs<NativeStorage>(stagingStorage); + return mLatestBufferStorage; } -Buffer11::PackStorage *Buffer11::getPackStorage() +gl::ErrorOrResult<Buffer11::NativeStorage *> Buffer11::getStagingStorage(const gl::Context *context) { - BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); - - if (!packStorage) - { - // Out-of-memory - return nullptr; - } + BufferStorage *stagingStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_STAGING), stagingStorage); + return GetAs<NativeStorage>(stagingStorage); +} +gl::ErrorOrResult<Buffer11::PackStorage *> Buffer11::getPackStorage(const gl::Context *context) +{ + BufferStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK), packStorage); return GetAs<PackStorage>(packStorage); } +size_t Buffer11::getSize() const +{ + return mSize; +} + bool Buffer11::supportsDirectBinding() const { // Do not support direct buffers for dynamic data. The streaming buffer // offers better performance for data which changes every frame. - // Check for absence of static buffer interfaces to detect dynamic data. - return (mStaticVertexBuffer && mStaticIndexBuffer); + return (mUsage == D3DBufferUsage::STATIC); +} + +void Buffer11::initializeStaticData(const gl::Context *context) +{ + BufferD3D::initializeStaticData(context); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(context); } +void Buffer11::invalidateStaticData(const gl::Context *context) +{ + BufferD3D::invalidateStaticData(context); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(context); +} + +OnBufferDataDirtyChannel *Buffer11::getStaticBroadcastChannel() +{ + return &mStaticBroadcastChannel; +} + +OnBufferDataDirtyChannel *Buffer11::getDirectBroadcastChannel() +{ + return &mDirectBroadcastChannel; +} + +void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source) +{ + ASSERT(source && mLatestBufferStorage); + dest->setDataRevision(source->getDataRevision()); + + // Only update the latest buffer storage if our usage index is lower. See comment in header. + if (dest->getUsage() < mLatestBufferStorage->getUsage()) + { + mLatestBufferStorage = dest; + } +} + +void Buffer11::onStorageUpdate(BufferStorage *updatedStorage) +{ + updatedStorage->setDataRevision(updatedStorage->getDataRevision() + 1); + mLatestBufferStorage = updatedStorage; +} + +// Buffer11::BufferStorage implementation + Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) { @@ -864,113 +971,118 @@ Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size) { - ASSERT(isMappable()); + ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT)); - uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT); - if (!writePointer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); - } + // 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, size); + memcpy(writePointer, data, mapSize); unmap(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) - : BufferStorage(renderer, usage), mNativeStorage(nullptr) +// Buffer11::NativeStorage implementation + +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const OnBufferDataDirtyChannel *onStorageChanged) + : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged) { } Buffer11::NativeStorage::~NativeStorage() { - SafeRelease(mNativeStorage); + clearSRVs(); } -// Returns true if it recreates the direct buffer -bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +bool Buffer11::NativeStorage::isCPUAccessible(GLbitfield access) const { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + 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(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ size_t requiredSize = destOffset + size; - bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + bool createBuffer = !mBuffer.valid() || mBufferSize < requiredSize; // (Re)initialize D3D buffer if needed + bool preserveData = (destOffset > 0); if (createBuffer) { - bool preserveData = (destOffset > 0); - resize(requiredSize, preserveData); + ANGLE_TRY(resize(context, 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()); - - uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); - ASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - source->unmap(); - return false; - } + ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT) && isCPUAccessible(GL_MAP_WRITE_BIT)); - uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset; + // Uniform buffers must be mapped with write/discard. + ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM)); - // Offset bounds are validated at the API layer - ASSERT(sourceOffset + size <= destOffset + mBufferSize); - memcpy(destPointer, sourcePointer, size); + uint8_t *sourcePointer = nullptr; + ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer)); - context->Unmap(mNativeStorage, 0); + auto err = setData(sourcePointer, destOffset, clampedSize); source->unmap(); + ANGLE_TRY(err); } else { D3D11_BOX srcBox; srcBox.left = static_cast<unsigned int>(sourceOffset); - srcBox.right = static_cast<unsigned int>(sourceOffset + size); + 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(); + const d3d11::Buffer *sourceBuffer = &GetAs<NativeStorage>(source)->getBuffer(); - context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0, - 0, sourceBuffer, 0, &srcBox); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mBuffer.get(), 0, + static_cast<unsigned int>(destOffset), 0, 0, + sourceBuffer->get(), 0, &srcBox); } - return createBuffer; + return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED; } -gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::NativeStorage::resize(const gl::Context *context, + 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); - } + FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size)); - d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage"); + d3d11::Buffer newBuffer; + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &newBuffer)); + newBuffer.setDebugName("Buffer11::NativeStorage"); - if (mNativeStorage && preserveData) + if (mBuffer.valid() && preserveData) { // We don't call resize if the buffer is big enough already. ASSERT(mBufferSize <= size); @@ -983,19 +1095,30 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) srcBox.front = 0; srcBox.back = 1; - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(newBuffer.get(), 0, 0, 0, 0, mBuffer.get(), 0, + &srcBox); } // No longer need the old buffer - SafeRelease(mNativeStorage); - mNativeStorage = newBuffer; + mBuffer = std::move(newBuffer); mBufferSize = bufferDesc.ByteWidth; - return gl::Error(GL_NO_ERROR); + // Free the SRVs. + clearSRVs(); + + // Notify that the storage has changed. + if (mOnStorageChanged) + { + mOnStorageChanged->signal(context); + } + + return gl::NoError(); } -void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, +// static +void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize) @@ -1030,6 +1153,13 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, bufferDesc->CPUAccessFlags = 0; break; + case BUFFER_USAGE_INDIRECT: + bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = 0; + break; + case BUFFER_USAGE_PIXEL_UNPACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; @@ -1044,9 +1174,12 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, // 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->getRendererCaps().maxUniformBlockSize)); + static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize)); break; default: @@ -1054,67 +1187,146 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, } } -uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::NativeStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { - ASSERT(mUsage == BUFFER_USAGE_STAGING); + ASSERT(isCPUAccessible(access)); D3D11_MAPPED_SUBRESOURCE mappedResource; ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); - UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + 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); + HRESULT result = context->Map(mBuffer.get(), 0, d3dMapType, d3dMapFlag, &mappedResource); ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return nullptr; + return gl::OutOfMemory() << "Failed to map native storage in Buffer11::NativeStorage::map"; } - return static_cast<uint8_t *>(mappedResource.pData) + offset; + ASSERT(mappedResource.pData); + *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset; + return gl::NoError(); } void Buffer11::NativeStorage::unmap() { - ASSERT(mUsage == BUFFER_USAGE_STAGING); + ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT) || isCPUAccessible(GL_MAP_READ_BIT)); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->Unmap(mNativeStorage, 0); + context->Unmap(mBuffer.get(), 0); +} + +gl::ErrorOrResult<const d3d11::ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat( + DXGI_FORMAT srvFormat) +{ + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + return &bufferSRVIt->second; + } + + 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; + + ANGLE_TRY(mRenderer->allocateResource(bufferSRVDesc, mBuffer.get(), + &mBufferResourceViews[srvFormat])); + + return &mBufferResourceViews[srvFormat]; +} + +void Buffer11::NativeStorage::clearSRVs() +{ + mBufferResourceViews.clear(); } +// Buffer11::EmulatedIndexStorage implementation + Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) - : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) + : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mBuffer() { } Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() { - SafeRelease(mNativeStorage); } -ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() +gl::ErrorOrResult<const d3d11::Buffer *> Buffer11::EmulatedIndexedStorage::getBuffer( + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) { - if (!mNativeStorage) + // 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 (!mBuffer.valid() || indexInfo->srcIndicesChanged) + { + mBuffer.reset(); + + // 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::OutOfMemory() << "Error resizing index memory buffer in " + "Buffer11::EmulatedIndexedStorage::getBuffer"; + } + + memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); + + indexInfo->srcIndicesChanged = false; + } + + if (!mBuffer.valid()) { + 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>((mIndexInfo.srcCount * mAttributeStride) + mAttributeOffset); - MemoryBuffer expandedData; + static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset); + angle::MemoryBuffer expandedData; if (!expandedData.resize(expandedDataSize)) { - return nullptr; + return gl::OutOfMemory() + << "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getBuffer"; } // 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 *>(mIndexInfo.srcIndices); + 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 += mAttributeOffset; + curr += offset; ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>; - switch (mIndexInfo.srcIndexType) + switch (indexInfo->srcIndexType) { case GL_UNSIGNED_INT: readIndexValue = ReadIndexValueFromIndices<GLuint>; @@ -1128,17 +1340,15 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() } // Iterate over the cached index data and copy entries indicated into the emulated buffer. - for (GLuint i = 0; i < mIndexInfo.srcCount; i++) + for (GLuint i = 0; i < indexInfo->srcCount; i++) { GLuint idx = readIndexValue(ptr, i); - memcpy(curr, mMemoryBuffer.data() + (mAttributeStride * idx), mAttributeStride); - curr += mAttributeStride; + 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; @@ -1149,99 +1359,53 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0}; - HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage); - if (FAILED(result)) - { - ERR("Could not create emulated index data buffer: %08lX", result); - return nullptr; - } - d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage"); + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &subResourceData, &mBuffer)); + mBuffer.setDebugName("Buffer11::EmulatedIndexedStorage"); } - return mNativeStorage; -} - -bool Buffer11::EmulatedIndexedStorage::update(SourceIndexData *indexInfo, - const TranslatedAttribute *attribute) -{ - // 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 attribute offset and stride information - mAttributeStride = attribute->stride; - mAttributeOffset = attribute->offset; - - // 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 false; - } - - memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); - - // Copy the source index data description and update the srcIndices pointer to point - // to our cached index data. - mIndexInfo = *indexInfo; - mIndexInfo.srcIndices = mIndicesMemoryBuffer.data(); - - indexInfo->srcIndicesChanged = false; - } - return true; + return &mBuffer; } -bool Buffer11::EmulatedIndexedStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage( + const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { - ASSERT(source->isMappable()); - const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(source->isCPUAccessible(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 true; + return CopyResult::RECREATED; } -gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::EmulatedIndexedStorage::resize(const gl::Context *context, + size_t size, + bool preserveData) { if (mMemoryBuffer.size() < size) { if (!mMemoryBuffer.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage"); + return gl::OutOfMemory() << "Failed to resize EmulatedIndexedStorage"; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::EmulatedIndexedStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size()); - return mMemoryBuffer.data() + offset; + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::NoError(); } void Buffer11::EmulatedIndexedStorage::unmap() @@ -1249,6 +1413,8 @@ void Buffer11::EmulatedIndexedStorage::unmap() // No-op } +// Buffer11::PackStorage implementation + Buffer11::PackStorage::PackStorage(Renderer11 *renderer) : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) { @@ -1258,32 +1424,42 @@ Buffer11::PackStorage::~PackStorage() { } -bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { - // We copy through a staging buffer when drawing with a pack buffer, - // or for other cases where we access the pack buffer - UNREACHABLE(); - return false; + ANGLE_TRY(flushQueuedPackCommand()); + + // For all use cases of pack buffers, we must copy through a readable buffer. + ASSERT(source->isCPUAccessible(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) +gl::Error Buffer11::PackStorage::resize(const gl::Context *context, 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."); + return gl::OutOfMemory() << "Failed to resize internal buffer storage."; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::PackStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(offset + length <= getSize()); // TODO: fast path @@ -1291,15 +1467,12 @@ uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield acc // and if D3D packs the staging texture memory identically to how we would fill // the pack buffer according to the current pack state. - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return nullptr; - } + ANGLE_TRY(flushQueuedPackCommand()); mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); - return mMemoryBuffer.data() + offset; + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::NoError(); } void Buffer11::PackStorage::unmap() @@ -1307,42 +1480,29 @@ void Buffer11::PackStorage::unmap() // No-op } -gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment, +gl::Error Buffer11::PackStorage::packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms) { - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(flushQueuedPackCommand()); RenderTarget11 *renderTarget = nullptr; - error = readAttachment.getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - ASSERT(renderTargetResource); + ANGLE_TRY(readAttachment.getRenderTarget(context, &renderTarget)); + const TextureHelper11 &srcTexture = renderTarget->getTexture(); + ASSERT(srcTexture.valid()); unsigned int srcSubresource = renderTarget->getSubresourceIndex(); - TextureHelper11 srcTexture = TextureHelper11::MakeAndReference(renderTargetResource); mQueuedPackCommand.reset(new PackPixelsParams(params)); gl::Extents srcTextureSize(params.area.width, params.area.height, 1); - if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() || + if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() || mStagingTexture.getExtents() != srcTextureSize) { - auto textureOrError = - CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormat(), - srcTextureSize, mRenderer->getDevice()); - if (textureOrError.isError()) - { - return textureOrError.getError(); - } - mStagingTexture = std::move(textureOrError.getResult()); + ANGLE_TRY_RESULT( + mRenderer->createStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(), + srcTextureSize, StagingAccess::READ), + mStagingTexture); } // ReadPixels from multisampled FBOs isn't supported in current GL @@ -1357,17 +1517,17 @@ gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &rea // Select the correct layer from a 3D attachment srcBox.front = 0; - if (mStagingTexture.getTextureType() == GL_TEXTURE_3D) + if (mStagingTexture.is3D()) { 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); + immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(), + srcSubresource, &srcBox); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Buffer11::PackStorage::flushQueuedPackCommand() @@ -1376,58 +1536,65 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() if (mQueuedPackCommand) { - gl::Error error = - mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + ANGLE_TRY( + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data())); mQueuedPackCommand.reset(nullptr); - if (error.isError()) - { - return error; - } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } +// Buffer11::SystemMemoryStorage implementation + Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) { } -bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage( + const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { - ASSERT(source->isMappable()); - const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(source->isCPUAccessible(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 true; + return CopyResult::RECREATED; } -gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::SystemMemoryStorage::resize(const gl::Context *context, + size_t size, + bool preserveData) { if (mSystemCopy.size() < size) { if (!mSystemCopy.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage"); + return gl::OutOfMemory() << "Failed to resize SystemMemoryStorage"; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::SystemMemoryStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size()); - return mSystemCopy.data() + offset; + *mapPointerOut = mSystemCopy.data() + offset; + return gl::NoError(); } void Buffer11::SystemMemoryStorage::unmap() { // No-op } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h index a748db57ae..ddbeeb90d2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -9,10 +9,12 @@ #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/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -21,69 +23,92 @@ 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, + // TODO: possibly share this buffer type with shader storage buffers. + BUFFER_USAGE_INDIRECT, BUFFER_USAGE_PIXEL_UNPACK, BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_UNIFORM, - BUFFER_USAGE_SYSTEM_MEMORY, BUFFER_USAGE_EMULATED_INDEXED_VERTEX, BUFFER_USAGE_COUNT, }; -struct PackPixelsParams -{ - PackPixelsParams(); - PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, - const gl::PixelPackState &pack, ptrdiff_t offset); - - gl::Rectangle area; - GLenum format; - GLenum type; - GLuint outputPitch; - gl::Buffer *packBuffer; - gl::PixelPackState pack; - ptrdiff_t offset; -}; - typedef size_t DataRevision; class Buffer11 : public BufferD3D { public: - Buffer11(Renderer11 *renderer); - virtual ~Buffer11(); - - ID3D11Buffer *getBuffer(BufferUsage usage); - ID3D11Buffer *getEmulatedIndexedBuffer(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); - ID3D11Buffer *getConstantBufferRange(GLintptr offset, GLsizeiptr size); - ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); - bool isMapped() const { return mMappedStorage != NULL; } - gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + Buffer11(const gl::BufferState &state, Renderer11 *renderer); + ~Buffer11() override; + + gl::ErrorOrResult<ID3D11Buffer *> getBuffer(const gl::Context *context, BufferUsage usage); + gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(const gl::Context *context, + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); + gl::Error getConstantBufferRange(const gl::Context *context, + GLintptr offset, + GLsizeiptr size, + const d3d11::Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut); + gl::ErrorOrResult<const d3d11::ShaderResourceView *> getSRV(const gl::Context *context, + DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != nullptr; } + gl::Error packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms); size_t getTotalCPUBufferMemoryBytes() const; // BufferD3D implementation - virtual size_t getSize() const { return mSize; } - virtual bool supportsDirectBinding() const; - gl::Error getData(const uint8_t **outData) override; + size_t getSize() const override; + bool supportsDirectBinding() const override; + gl::Error getData(const gl::Context *context, const uint8_t **outData) override; + void initializeStaticData(const gl::Context *context) override; + void invalidateStaticData(const gl::Context *context) override; // BufferImpl implementation - virtual gl::Error setData(const void* data, size_t size, GLenum usage); - virtual gl::Error setSubData(const void* data, size_t size, size_t offset); - virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(GLenum access, GLvoid **mapPtr); - virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(GLboolean *result); - virtual void markTransformFeedbackUsage(); + gl::Error setData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + gl::BufferUsage usage) override; + gl::Error setSubData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + size_t offset) override; + gl::Error copySubData(const gl::Context *context, + BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) override; + gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override; + gl::Error mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) override; + gl::Error unmap(const gl::Context *context, GLboolean *result) override; + gl::Error markTransformFeedbackUsage(const gl::Context *context) 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. + OnBufferDataDirtyChannel *getStaticBroadcastChannel(); + OnBufferDataDirtyChannel *getDirectBroadcastChannel(); private: class BufferStorage; @@ -92,21 +117,61 @@ class Buffer11 : public BufferD3D class PackStorage; class SystemMemoryStorage; - Renderer11 *mRenderer; - size_t mSize; - - BufferStorage *mMappedStorage; - - std::vector<BufferStorage*> mBufferStorages; - struct ConstantBufferCacheEntry { - ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { } + ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {} BufferStorage *storage; unsigned int lruCount; }; + void markBufferUsage(BufferUsage usage); + gl::Error garbageCollection(const gl::Context *context, BufferUsage currentUsage); + gl::ErrorOrResult<NativeStorage *> getStagingStorage(const gl::Context *context); + gl::ErrorOrResult<PackStorage *> getPackStorage(const gl::Context *context); + gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage(const gl::Context *context); + + gl::Error updateBufferStorage(const gl::Context *context, + BufferStorage *storage, + size_t sourceOffset, + size_t storageSize); + gl::ErrorOrResult<BufferStorage *> getBufferStorage(const gl::Context *context, + BufferUsage usage); + gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage(const gl::Context *context) const; + + gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(const gl::Context *context, + 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(const gl::Context *context, BufferUsage usage); + + // For some cases of uniform buffer storage, we can't deallocate system memory storage. + bool canDeallocateSystemMemory() const; + + // Updates data revisions and latest storage. + void onCopyStorage(BufferStorage *dest, BufferStorage *source); + void onStorageUpdate(BufferStorage *updatedStorage); + + Renderer11 *mRenderer; + size_t mSize; + + BufferStorage *mMappedStorage; + + // Buffer storages are sorted by usage. It's important that the latest buffer storage picks + // the lowest usage in the case where two storages are tied on data revision - this ensures + // we never do anything dangerous like map a uniform buffer over a staging or system memory + // copy. + std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages; + BufferStorage *mLatestBufferStorage; + + // 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. @@ -115,25 +180,10 @@ class Buffer11 : public BufferD3D size_t mConstantBufferStorageAdditionalSize; unsigned int mMaxConstantBufferLruCount; - typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair; - std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews; - - unsigned int mReadUsageCount; - - void markBufferUsage(); - NativeStorage *getStagingStorage(); - PackStorage *getPackStorage(); - gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut); - - void updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize); - BufferStorage *getBufferStorage(BufferUsage usage); - BufferStorage *getLatestBufferStorage() const; - - BufferStorage *getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size); - - void invalidateEmulatedIndexedBuffer(); + OnBufferDataDirtyChannel mStaticBroadcastChannel; + OnBufferDataDirtyChannel mDirectBroadcastChannel; }; -} +} // namespace rx -#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp index cd95c65d1c..f9dda0aeb4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -1,4 +1,4 @@ -// + // 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. @@ -20,624 +20,814 @@ #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/clear11_fl9vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.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" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h" namespace rx { +namespace +{ +constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo<float>); +constexpr uint32_t g_VertexSize = sizeof(d3d11::PositionVertex); + +// Updates color, depth and alpha components of cached CB if necessary. +// Returns true if any constants are updated, false otherwise. template <typename T> -static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color<T> &color, float depth, void *buffer) +bool UpdateDataCache(RtvDsvClearInfo<T> *dataCache, + const gl::Color<T> &color, + const float *zValue, + const uint32_t numRtvs, + const uint8_t writeMask) { - d3d11::PositionDepthColorVertex<T> *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex<T>*>(buffer); + bool cacheDirty = false; + + if (numRtvs > 0) + { + const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0; + if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0) + { + dataCache->r = color.red; + dataCache->g = color.green; + dataCache->b = color.blue; + cacheDirty = true; + } - float depthClear = gl::clamp01(depth); - float left = -1.0f; - float right = 1.0f; - float top = -1.0f; - float bottom = 1.0f; + const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0; + if (writeAlpha && (dataCache->a != color.alpha)) + { + dataCache->a = color.alpha; + cacheDirty = true; + } + } - // Clip the quad coordinates to the scissor if needed - if (scissor != nullptr) + if (zValue) { - 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); + const float clampedZValue = gl::clamp01(*zValue); + + if (clampedZValue != dataCache->z) + { + dataCache->z = clampedZValue; + cacheDirty = true; + } } - 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); + return cacheDirty; } -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) +bool AllOffsetsAreNonNegative(const std::vector<gl::Offset> &viewportOffsets) { - D3D11_INPUT_ELEMENT_DESC quadLayout[] = + for (size_t i = 0u; i < viewportOffsets.size(); ++i) { - { "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); + const auto &offset = viewportOffsets[i]; + if (offset.x < 0 || offset.y < 0) + { + return false; + } + } + return true; } - -Clear11::ClearShader::~ClearShader() +} // anonymous namespace + +#define CLEARPS(Index) \ + d3d11::LazyShader<ID3D11PixelShader>(g_PS_Clear##Index, ArraySize(g_PS_Clear##Index), \ + "Clear11 PS " ANGLE_STRINGIFY(Index)) + +Clear11::ShaderManager::ShaderManager() + : mIl9(), + mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"), + mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"), + mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"), + mVsMultiview(g_VS_Multiview_Clear, ArraySize(g_VS_Multiview_Clear), "Clear11 VS Multiview"), + mGsMultiview(g_GS_Multiview_Clear, ArraySize(g_GS_Multiview_Clear), "Clear11 GS Multiview"), + mPsDepth(g_PS_ClearDepth, ArraySize(g_PS_ClearDepth), "Clear11 PS Depth"), + mPsFloat{{CLEARPS(Float1), CLEARPS(Float2), CLEARPS(Float3), CLEARPS(Float4), CLEARPS(Float5), + CLEARPS(Float6), CLEARPS(Float7), CLEARPS(Float8)}}, + mPsUInt{{CLEARPS(Uint1), CLEARPS(Uint2), CLEARPS(Uint3), CLEARPS(Uint4), CLEARPS(Uint5), + CLEARPS(Uint6), CLEARPS(Uint7), CLEARPS(Uint8)}}, + mPsSInt{{CLEARPS(Sint1), CLEARPS(Sint2), CLEARPS(Sint3), CLEARPS(Sint4), CLEARPS(Sint5), + CLEARPS(Sint6), CLEARPS(Sint7), CLEARPS(Sint8)}} { - 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) +#undef CLEARPS + +Clear11::ShaderManager::~ShaderManager() { - TRACE_EVENT0("gpu.angle", "Clear11::Clear11"); +} - HRESULT result; - ID3D11Device *device = renderer->getDevice(); +gl::Error Clear11::ShaderManager::getShadersAndLayout(Renderer11 *renderer, + const INT clearType, + const uint32_t numRTs, + const bool hasLayeredLayout, + const d3d11::InputLayout **il, + const d3d11::VertexShader **vs, + const d3d11::GeometryShader **gs, + const d3d11::PixelShader **ps) +{ + if (renderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(clearType == GL_FLOAT); - 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; + ANGLE_TRY(mVs9.resolve(renderer)); + ANGLE_TRY(mPsFloat9.resolve(renderer)); - result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + if (!mIl9.valid()) + { + const D3D11_INPUT_ELEMENT_DESC ilDesc[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}}; - 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; + InputElementArray ilDescArray(ilDesc); + ShaderData vertexShader(g_VS_Clear_FL9); - result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + ANGLE_TRY(renderer->allocateResource(ilDescArray, &vertexShader, &mIl9)); + } - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + *vs = &mVs9.getObj(); + *gs = nullptr; + *il = &mIl9; + *ps = &mPsFloat9.getObj(); + return gl::NoError(); + } + if (!hasLayeredLayout) { - 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"); + ANGLE_TRY(mVs.resolve(renderer)); + *vs = &mVs.getObj(); + *gs = nullptr; } 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"); + // For layered framebuffers we have to use the multi-view versions of the VS and GS. + ANGLE_TRY(mVsMultiview.resolve(renderer)); + ANGLE_TRY(mGsMultiview.resolve(renderer)); + *vs = &mVsMultiview.getObj(); + *gs = &mGsMultiview.getObj(); + } + + *il = nullptr; + + if (numRTs == 0) + { + ANGLE_TRY(mPsDepth.resolve(renderer)); + *ps = &mPsDepth.getObj(); + return gl::NoError(); } - if (renderer->isES3Capable()) + switch (clearType) { - 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"); + case GL_FLOAT: + ANGLE_TRY(mPsFloat[numRTs - 1].resolve(renderer)); + *ps = &mPsFloat[numRTs - 1].getObj(); + break; + case GL_UNSIGNED_INT: + ANGLE_TRY(mPsUInt[numRTs - 1].resolve(renderer)); + *ps = &mPsUInt[numRTs - 1].getObj(); + break; + case GL_INT: + ANGLE_TRY(mPsSInt[numRTs - 1].resolve(renderer)); + *ps = &mPsSInt[numRTs - 1].getObj(); + break; + default: + UNREACHABLE(); + break; } + + return gl::NoError(); +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), + mResourcesInitialized(false), + mScissorEnabledRasterizerState(), + mScissorDisabledRasterizerState(), + mShaderManager(), + mConstantBuffer(), + mVertexBuffer(), + mShaderData({}) +{ } Clear11::~Clear11() { - for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) +} + +gl::Error Clear11::ensureResourcesInitialized() +{ + if (mResourcesInitialized) { - SafeRelease(i->second); + return gl::NoError(); } - mClearBlendStates.clear(); - SafeDelete(mFloatClearShader); - SafeDelete(mUintClearShader); - SafeDelete(mIntClearShader); + TRACE_EVENT0("gpu.angle", "Clear11::ensureResourcesInitialized"); + + static_assert((sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<int>)), + "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<int>"); + + static_assert( + (sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<uint32_t>)), + "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<uint32_t>"); - for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) + static_assert((sizeof(RtvDsvClearInfo<float>) % 16 == 0), + "The size of RtvDsvClearInfo<float> should be a multiple of 16bytes."); + + // Create Rasterizer States + 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; + + ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorDisabledRasterizerState)); + mScissorDisabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor disabled"); + + rsDesc.ScissorEnable = TRUE; + ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorEnabledRasterizerState)); + mScissorEnabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor enabled"); + + // Initialize Depthstencil state with defaults + mDepthStencilStateKey.depthTest = false; + mDepthStencilStateKey.depthMask = false; + mDepthStencilStateKey.depthFunc = GL_ALWAYS; + mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1); + mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1); + mDepthStencilStateKey.stencilBackMask = 0; + mDepthStencilStateKey.stencilTest = false; + mDepthStencilStateKey.stencilMask = 0; + mDepthStencilStateKey.stencilFail = GL_REPLACE; + mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE; + mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE; + mDepthStencilStateKey.stencilFunc = GL_ALWAYS; + mDepthStencilStateKey.stencilBackFail = GL_REPLACE; + mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE; + mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE; + mDepthStencilStateKey.stencilBackFunc = GL_ALWAYS; + + // Initialize BlendStateKey with defaults + mBlendStateKey.blendState.blend = false; + mBlendStateKey.blendState.sourceBlendRGB = GL_ONE; + mBlendStateKey.blendState.sourceBlendAlpha = GL_ONE; + mBlendStateKey.blendState.destBlendRGB = GL_ZERO; + mBlendStateKey.blendState.destBlendAlpha = GL_ZERO; + mBlendStateKey.blendState.blendEquationRGB = GL_FUNC_ADD; + mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD; + mBlendStateKey.blendState.sampleAlphaToCoverage = false; + mBlendStateKey.blendState.dither = true; + + mResourcesInitialized = true; + return gl::NoError(); +} + +bool Clear11::useVertexBuffer() const +{ + return (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3); +} + +gl::Error Clear11::ensureConstantBufferCreated() +{ + if (mConstantBuffer.valid()) { - SafeRelease(i->second); + return gl::NoError(); } - mClearDepthStencilStates.clear(); - SafeRelease(mVertexBuffer); - SafeRelease(mRasterizerState); + // Create constant buffer for color & depth data + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = g_ConstantBufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = &mShaderData; + initialData.SysMemPitch = g_ConstantBufferSize; + initialData.SysMemSlicePitch = g_ConstantBufferSize; + + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mConstantBuffer)); + mConstantBuffer.setDebugName("Clear11 Constant Buffer"); + return gl::NoError(); } -gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) +gl::Error Clear11::ensureVertexBufferCreated() { - const auto &colorAttachments = fboData.getColorAttachments(); - const auto &drawBufferStates = fboData.getDrawBufferStates(); - const auto *depthAttachment = fboData.getDepthAttachment(); - const auto *stencilAttachment = fboData.getStencilAttachment(); + ASSERT(useVertexBuffer()); + + if (mVertexBuffer.valid()) + { + return gl::NoError(); + } + + // Create vertex buffer with vertices for a quad covering the entire surface + + static_assert((sizeof(d3d11::PositionVertex) % 16) == 0, + "d3d11::PositionVertex should be a multiple of 16 bytes"); + const d3d11::PositionVertex vbData[6] = {{-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}, + {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, + {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}}; + + const UINT vbSize = sizeof(vbData); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = vbSize; + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = vbData; + initialData.SysMemPitch = vbSize; + initialData.SysMemSlicePitch = initialData.SysMemPitch; + + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mVertexBuffer)); + mVertexBuffer.setDebugName("Clear11 Vertex Buffer"); + return gl::NoError(); +} - ASSERT(colorAttachments.size() == drawBufferStates.size()); +gl::Error Clear11::clearFramebuffer(const gl::Context *context, + const ClearParameters &clearParams, + const gl::FramebufferState &fboData) +{ + ANGLE_TRY(ensureResourcesInitialized()); // 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) + // 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. + // 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. + // Otherwise perform a shader based clear. // - // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView - // by checking if the stencil write mask covers the entire stencil. + // Also determine if the DSV can be cleared withID3D11DeviceContext::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. + // To clear the remaining buffers, a shader based clear is performed: + // - The appropriate ShaderManagers (VS & PS) for the clearType is set + // - A CB containing the clear color and Z values is bound + // - An IL and VB are bound (for FL93 and below) + // - ScissorRect/Raststate/Viewport set as required + // - Blendstate set containing appropriate colorMasks + // - DepthStencilState set with appropriate parameters for a z or stencil clear if required + // - Color and/or Z buffers to be cleared are bound + // - Primitive covering entire clear area is drawn 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) + const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment(); + if (depthStencilAttachment != nullptr) { - framebufferSize = stencilAttachment->getSize(); + framebufferSize = depthStencilAttachment->getSize(); } else { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); + + if (!colorAttachment) + { + UNREACHABLE(); + return gl::InternalError(); + } + + framebufferSize = colorAttachment->getSize(); } - 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)) + const bool isSideBySideFBO = + (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE); + bool needScissoredClear = false; + std::vector<D3D11_RECT> scissorRects; + if (clearParams.scissorEnabled) { - // Scissor is enabled and the scissor rectangle is outside the renderbuffer - return gl::Error(GL_NO_ERROR); - } + const std::vector<gl::Offset> *viewportOffsets = fboData.getViewportOffsets(); + ASSERT(viewportOffsets != nullptr); + ASSERT(AllOffsetsAreNonNegative(*fboData.getViewportOffsets())); - 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); + if (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.width == 0 || + clearParams.scissor.height == 0) + { + // The check assumes that the viewport offsets are not negative as according to the + // ANGLE_multiview spec. + // Scissor rect is outside the renderbuffer or is an empty rect. + return gl::NoError(); + } - std::vector<MaskedRenderTarget> maskedClearRenderTargets; - RenderTarget11* maskedClearDepthStencil = nullptr; + if (isSideBySideFBO) + { + // We always have to do a scissor clear for side-by-side framebuffers. + needScissoredClear = true; + } + else + { + // Because the viewport offsets can generate scissor rectangles within the framebuffer's + // bounds, we can do this check only for non-side-by-side framebuffers. + if (clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0) + { + // Scissor rect is outside the renderbuffer. + return gl::NoError(); + } + needScissoredClear = + clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height; + } - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); -#if defined(ANGLE_ENABLE_D3D11_1) + if (needScissoredClear) + { + // Apply viewport offsets to compute the final scissor rectangles. This is valid also + // for non-side-by-side framebuffers, because the default viewport offset is {0,0}. + const size_t numViews = viewportOffsets->size(); + scissorRects.reserve(numViews); + for (size_t i = 0u; i < numViews; ++i) + { + const gl::Offset &offset = (*viewportOffsets)[i]; + D3D11_RECT rect; + int x = clearParams.scissor.x + offset.x; + int y = clearParams.scissor.y + offset.y; + rect.left = x; + rect.right = x + clearParams.scissor.width; + rect.top = y; + rect.bottom = y + clearParams.scissor.height; + scissorRects.emplace_back(rect); + } + } + } + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); -#endif - ID3D11Device *device = mRenderer->getDevice(); - for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); - colorAttachmentIndex++) + std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs; + std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks = {}; + + uint32_t numRtvs = 0; + const uint8_t colorMask = + gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen, + clearParams.colorMaskBlue, clearParams.colorMaskAlpha); + + const auto &colorAttachments = fboData.getColorAttachments(); + for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers()) { const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex]; - if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() && - drawBufferStates[colorAttachmentIndex] != GL_NONE) + if (!clearParams.clearColor[colorAttachmentIndex]) { - RenderTarget11 *renderTarget = nullptr; - gl::Error error = attachment.getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + continue; + } - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment.getInternalFormat()); + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment.getRenderTarget(context, &renderTarget)); - 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.getInternalFormat()); - } + const gl::InternalFormat &formatInfo = *attachment.getFormat().info; - 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 + if (clearParams.colorType == 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 " + << colorAttachmentIndex << " has internal format " << attachment.getFormat() + << ")."; + } - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } + 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; + } - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + const auto &framebufferRTV = renderTarget->getRenderTargetView(); + ASSERT(framebufferRTV.valid()); - // 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 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - }; + if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) || + clearParams.colorType != GL_FLOAT || + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + rtvs[numRtvs] = framebufferRTV.get(); + rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask; + numRtvs++; + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is + // possible + + 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.colorF.red), + ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0) + ? 0.0f + : clearParams.colorF.green), + ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f + : clearParams.colorF.blue), + ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0) + ? 1.0f + : clearParams.colorF.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.colorF.alpha >= 0.5f) ? 1.0f : 0.0f; + } - if (dxgiFormatInfo.alphaBits == 1) + if (needScissoredClear) + { + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + // There must be at least one scissor rectangle. + ASSERT(!scissorRects.empty()); + deviceContext1->ClearView(framebufferRTV.get(), clearValues, scissorRects.data(), + static_cast<UINT>(scissorRects.size())); + if (mRenderer->getWorkarounds().callClearTwice) { - // 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; + deviceContext1->ClearView(framebufferRTV.get(), clearValues, + scissorRects.data(), + static_cast<UINT>(scissorRects.size())); } - -#if defined(ANGLE_ENABLE_D3D11_1) - 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); - } - else -#endif + } + else + { + deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues); + if (mRenderer->getWorkarounds().callClearTwice) { - deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues); } } } } + ID3D11DepthStencilView *dsv = nullptr; + if (clearParams.clearDepth || clearParams.clearStencil) { - const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; - ASSERT(attachment != nullptr); + RenderTarget11 *depthStencilRenderTarget = nullptr; - RenderTarget11 *renderTarget = nullptr; - gl::Error error = attachment->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ASSERT(depthStencilAttachment != nullptr); + ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget)); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + dsv = depthStencilRenderTarget->getDepthStencilView().get(); + ASSERT(dsv != nullptr); - unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; - bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format(); + const auto *stencilAttachment = fboData.getStencilAttachment(); - if (needScissoredClear || needMaskedStencilClear) - { - maskedClearDepthStencil = renderTarget; - } - else + uint32_t stencilUnmasked = + (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0; + bool needMaskedStencilClear = + clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (!needScissoredClear && !needMaskedStencilClear) { - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); - } + const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + const FLOAT depthClear = gl::clamp01(clearParams.depthValue); + const UINT8 stencilClear = clearParams.stencilValue & 0xFF; - 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(dsv, clearFlags, depthClear, stencilClear); - deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + dsv = nullptr; } } - if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) + if (numRtvs == 0 && dsv == nullptr) { - // 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->getRendererCaps().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."); - } + return gl::NoError(); + } - rtvs[i] = rtv; - } - ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr; + // Clear the remaining render targets and depth stencil in one pass by rendering a quad: + // + // IA/VS: Vertices containing position and color members are passed through to the next stage. + // The vertex position has XY coordinates equal to clip extents and a Z component equal to the + // Z clear value. The vertex color contains the clear color. + // + // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether + // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without + // the scissor test enabled is set as well. + // + // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or + // disabled or set depending on what the input depthStencil clear parameters are. Since the PS + // is not writing out depth or rejecting pixels, this should happen prior to the PS stage. + // + // PS: Will write out the color values passed through from the previous stage to all outputs. + // + // OM: BlendState will perform the required color masking and output to RTV(s). + + // + // ====================================================================================== + // + // 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. - ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); - const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - const UINT sampleMask = 0xFFFFFFFF; + ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers); - ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); - const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + // Setup BlendStateKey parameters + mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed; + mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen; + mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue; + mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha; + mBlendStateKey.rtvMax = numRtvs; + memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks)); - // 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); - } + // Get BlendState + const d3d11::BlendState *blendState = nullptr; + ANGLE_TRY(mRenderer->getBlendState(mBlendStateKey, &blendState)); - 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; + const d3d11::DepthStencilState *dsState = nullptr; + const float *zValue = nullptr; - case GL_UNSIGNED_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); - shader = mUintClearShader; - break; + if (dsv) + { + // Setup DepthStencilStateKey + mDepthStencilStateKey.depthTest = clearParams.clearDepth; + mDepthStencilStateKey.depthMask = clearParams.clearDepth; + mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask; + mDepthStencilStateKey.stencilTest = clearParams.clearStencil; + + // Get DepthStencilState + ANGLE_TRY(mRenderer->getDepthStencilState(mDepthStencilStateKey, &dsState)); + zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr; + } - case GL_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); - shader = mIntClearShader; - break; + bool dirtyCb = false; - default: + // Compare the input color/z values against the CB cache and update it if necessary + switch (clearParams.colorType) + { + case GL_FLOAT: + dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<float> *>(&mShaderData), + clearParams.colorF, zValue, numRtvs, colorMask); + break; + case GL_UNSIGNED_INT: + dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<uint32_t> *>(&mShaderData), + clearParams.colorUI, zValue, numRtvs, colorMask); + break; + case GL_INT: + dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<int> *>(&mShaderData), + clearParams.colorI, zValue, numRtvs, colorMask); + 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 - deviceContext->OMSetRenderTargets(static_cast<unsigned int>(rtvs.size()), - (rtvs.empty() ? nullptr : &rtvs[0]), dsv); - - // Draw the clear quad - deviceContext->Draw(4, 0); - - // Clean up - mRenderer->markAllStateDirty(); } - return gl::Error(GL_NO_ERROR); -} + ANGLE_TRY(ensureConstantBufferCreated()); -ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts) -{ - ClearBlendInfo blendKey = {}; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + if (dirtyCb) { - 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 + // Update the constant buffer with the updated cache contents + // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible. + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, + &mappedResource); + if (FAILED(result)) { - blendKey.maskChannels[i][0] = false; - blendKey.maskChannels[i][1] = false; - blendKey.maskChannels[i][2] = false; - blendKey.maskChannels[i][3] = false; + return gl::OutOfMemory() << "Clear11: Failed to map CB, " << gl::FmtHR(result); } - } - ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); - if (i != mClearBlendStates.end()) - { - return i->second; + memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize); + deviceContext->Unmap(mConstantBuffer.get(), 0); } - 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]); - } + auto *stateManager = mRenderer->getStateManager(); - 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; - } + // Set the viewport to be the same size as the framebuffer. + stateManager->setSimpleViewport(framebufferSize); - mClearBlendStates[blendKey] = blendState; + // Apply state + stateManager->setSimpleBlendState(blendState); - return blendState; - } -} + const UINT stencilValue = clearParams.stencilValue & 0xFF; + stateManager->setDepthStencilState(dsState, stencilValue); -ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams) -{ - ClearDepthStencilInfo dsKey = { 0 }; - dsKey.clearDepth = clearParams.clearDepth; - dsKey.clearStencil = clearParams.clearStencil; - dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + if (needScissoredClear) + { + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); + } + else + { + stateManager->setRasterizerState(&mScissorDisabledRasterizerState); + } - ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); - if (i != mClearDepthStencilStates.end()) + // Get Shaders + const d3d11::VertexShader *vs = nullptr; + const d3d11::GeometryShader *gs = nullptr; + const d3d11::InputLayout *il = nullptr; + const d3d11::PixelShader *ps = nullptr; + const bool hasLayeredLayout = + (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE); + ANGLE_TRY(mShaderManager.getShadersAndLayout(mRenderer, clearParams.colorType, numRtvs, + hasLayeredLayout, &il, &vs, &gs, &ps)); + + // Apply Shaders + stateManager->setDrawShaders(vs, gs, ps); + stateManager->setPixelConstantBuffer(0, &mConstantBuffer); + + // Bind IL & VB if needed + stateManager->setIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0); + stateManager->setInputLayout(il); + + if (useVertexBuffer()) { - return i->second; + ANGLE_TRY(ensureVertexBufferCreated()); + stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0); } 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; - } + stateManager->setSingleVertexBuffer(nullptr, 0, 0); + } - mClearDepthStencilStates[dsKey] = dsState; + stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - return dsState; + // Apply render targets + stateManager->setRenderTargets(&rtvs[0], numRtvs, dsv); + + // If scissors are necessary to be applied, then the number of clears is the number of scissor + // rects. If no scissors are necessary, then a single full-size clear is enough. + size_t necessaryNumClears = needScissoredClear ? scissorRects.size() : 1u; + for (size_t i = 0u; i < necessaryNumClears; ++i) + { + if (needScissoredClear) + { + ASSERT(i < scissorRects.size()); + stateManager->setScissorRectD3D(scissorRects[i]); + } + // Draw the fullscreen quad. + if (!hasLayeredLayout || isSideBySideFBO) + { + deviceContext->Draw(6, 0); + } + else + { + ASSERT(hasLayeredLayout); + deviceContext->DrawInstanced(6, static_cast<UINT>(fboData.getNumViews()), 0, 0); + } } -} + return gl::NoError(); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h index 3ff73c85d1..a09812c42b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -23,6 +23,14 @@ class Renderer11; class RenderTarget11; struct ClearParameters; +template <typename T> +struct RtvDsvClearInfo +{ + T r, g, b, a; + float z; + float c1padding[3]; +}; + class Clear11 : angle::NonCopyable { public: @@ -30,68 +38,63 @@ class Clear11 : angle::NonCopyable ~Clear11(); // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData); + gl::Error clearFramebuffer(const gl::Context *context, + 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 + class ShaderManager final : 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; + public: + ShaderManager(); + ~ShaderManager(); + gl::Error getShadersAndLayout(Renderer11 *renderer, + const INT clearType, + const uint32_t numRTs, + const bool hasLayeredLayout, + const d3d11::InputLayout **il, + const d3d11::VertexShader **vs, + const d3d11::GeometryShader **gs, + const d3d11::PixelShader **ps); + + private: + constexpr static size_t kNumShaders = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + d3d11::InputLayout mIl9; + d3d11::LazyShader<ID3D11VertexShader> mVs9; + d3d11::LazyShader<ID3D11PixelShader> mPsFloat9; + d3d11::LazyShader<ID3D11VertexShader> mVs; + d3d11::LazyShader<ID3D11VertexShader> mVsMultiview; + d3d11::LazyShader<ID3D11GeometryShader> mGsMultiview; + d3d11::LazyShader<ID3D11PixelShader> mPsDepth; + std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsFloat; + std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsUInt; + std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsSInt; }; - 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; + bool useVertexBuffer() const; + gl::Error ensureConstantBufferCreated(); + gl::Error ensureVertexBufferCreated(); + gl::Error ensureResourcesInitialized(); Renderer11 *mRenderer; + bool mResourcesInitialized; - ClearBlendStateMap mClearBlendStates; - - ClearShader *mFloatClearShader; - ClearShader *mUintClearShader; - ClearShader *mIntClearShader; + // States + d3d11::RasterizerState mScissorEnabledRasterizerState; + d3d11::RasterizerState mScissorDisabledRasterizerState; + gl::DepthStencilState mDepthStencilStateKey; + d3d11::BlendStateKey mBlendStateKey; - ClearDepthStencilStateMap mClearDepthStencilStates; + // Shaders and shader resources + ShaderManager mShaderManager; + d3d11::Buffer mConstantBuffer; + d3d11::Buffer mVertexBuffer; - ID3D11Buffer *mVertexBuffer; - ID3D11RasterizerState *mRasterizerState; + // Buffer data and draw parameters + RtvDsvClearInfo<float> mShaderData; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp new file mode 100644 index 0000000000..b79dd3603a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp @@ -0,0 +1,405 @@ +// +// 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/Context.h" +#include "libANGLE/MemoryProgramCache.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.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/ProgramPipeline11.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(), mRenderer->getNativeExtensions()); +} + +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); + case GL_TEXTURE_2D_MULTISAMPLE: + return new TextureD3D_2DMultisample(state, mRenderer); + break; + 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); +} + +SyncImpl *Context11::createSync() +{ + return new Sync11(mRenderer); +} + +TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state) +{ + return new TransformFeedback11(state, mRenderer); +} + +SamplerImpl *Context11::createSampler(const gl::SamplerState &state) +{ + return new SamplerD3D(state); +} + +ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data) +{ + return new ProgramPipeline11(data); +} + +std::vector<PathImpl *> Context11::createPaths(GLsizei) +{ + return std::vector<PathImpl *>(); +} + +gl::Error Context11::flush(const gl::Context *context) +{ + return mRenderer->flush(); +} + +gl::Error Context11::finish(const gl::Context *context) +{ + return mRenderer->finish(); +} + +gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArrays(context, mode, first, count, 0); +} + +gl::Error Context11::drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArrays(context, mode, first, count, instanceCount); +} + +gl::Error Context11::drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context11::drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, instances); +} + +gl::Error Context11::drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context11::drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArraysIndirect(context, mode, indirect); +} + +gl::Error Context11::drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElementsIndirect(context, mode, type, indirect); +} + +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::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) +{ + // Fall through to the EXT_debug_marker functions + pushGroupMarker(length, message); +} + +void Context11::popDebugGroup() +{ + // Fall through to the EXT_debug_marker functions + popGroupMarker(); +} + +void Context11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(context, dirtyBits); +} + +GLint Context11::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 Context11::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void Context11::onMakeCurrent(const gl::Context *context) +{ + ANGLE_SWALLOW_ERR(mRenderer->getStateManager()->onMakeCurrent(context)); +} + +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(); +} + +gl::Error Context11::dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ); +} + +gl::Error Context11::triggerDrawCallProgramRecompilation(const gl::Context *context, + GLenum drawMode) +{ + const auto &glState = context->getGLState(); + const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray()); + const auto *drawFBO = glState.getDrawFramebuffer(); + gl::Program *program = glState.getProgram(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + + programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); + programD3D->updateCachedOutputLayout(context, drawFBO); + + bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout(); + bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(drawMode); + bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout(); + + if (!recompileVS && !recompileGS && !recompilePS) + { + return gl::NoError(); + } + + // Load the compiler if necessary and recompile the programs. + ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized()); + + gl::InfoLog infoLog; + + if (recompileVS) + { + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, &infoLog)); + if (!programD3D->hasVertexExecutableForCachedInputLayout()) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic vertex executable:" << infoLog.str(); + } + } + + if (recompileGS) + { + ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, + &infoLog)); + if (!programD3D->hasGeometryExecutableForPrimitiveType(drawMode)) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic geometry executable:" << infoLog.str(); + } + } + + if (recompilePS) + { + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, &infoLog)); + if (!programD3D->hasPixelExecutableForCachedOutputLayout()) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic pixel executable:" << infoLog.str(); + } + } + + // Refresh the program cache entry. + if (mMemoryProgramCache) + { + mMemoryProgramCache->updateProgram(context, program); + } + + return gl::NoError(); +} + +gl::Error Context11::prepareForDrawCall(const gl::Context *context, GLenum drawMode) +{ + ANGLE_TRY(mRenderer->getStateManager()->updateState(context, drawMode)); + return gl::NoError(); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h new file mode 100644 index 0000000000..dd99111b19 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h @@ -0,0 +1,155 @@ +// +// 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; + SyncImpl *createSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler(const gl::SamplerState &state) override; + + // Program Pipeline object creation + ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override; + + // Path object creation. + std::vector<PathImpl *> createPaths(GLsizei) override; + + // Flush and finish. + gl::Error flush(const gl::Context *context) override; + gl::Error finish(const gl::Context *context) override; + + // Drawing methods. + gl::Error drawArrays(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count) override; + gl::Error drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) override; + gl::Error drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) override; + gl::Error drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // EXT_debug_marker + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // KHR_debug + void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override; + void popDebugGroup() override; + + // State sync with dirty bits. + void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::Context *context) 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; } + + gl::Error dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) override; + + gl::Error triggerDrawCallProgramRecompilation(const gl::Context *context, GLenum drawMode); + + private: + gl::Error prepareForDrawCall(const gl::Context *context, GLenum drawMode); + + Renderer11 *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp index 1c35ab45cc..1e70363e11 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -27,9 +27,7 @@ DebugAnnotator11::~DebugAnnotator11() { if (mInitialized) { -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(mUserDefinedAnnotation); -#endif #if !defined(ANGLE_ENABLE_WINDOWS_STORE) FreeLibrary(mD3d11Module); @@ -43,9 +41,7 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName) if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->BeginEvent(eventName); -#endif } } @@ -55,9 +51,7 @@ void DebugAnnotator11::endEvent() if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->EndEvent(); -#endif } } @@ -67,16 +61,14 @@ void DebugAnnotator11::setMarker(const wchar_t *markerName) if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->SetMarker(markerName); -#endif } } bool DebugAnnotator11::getStatus() { #if defined(ANGLE_ENABLE_WINDOWS_STORE) -#if (NTDDI_VERSION == NTDDI_WIN10) + static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above"); initializeDevice(); if (mUserDefinedAnnotation != nullptr) @@ -85,38 +77,6 @@ bool DebugAnnotator11::getStatus() } return true; // Default if initializeDevice() failed -#elif defined(_DEBUG) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) - static bool underCapture = true; - - // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in - // Windows 8.1/Visual Studio 2013. We can use IDXGraphicsAnalysis, though. - // The call to GetDebugInterface1 only succeeds if the app is under capture. - // This should only be called in DEBUG mode. - // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows - // Store ingestion checks. - - // Cache the result to reduce the number of calls to DXGIGetDebugInterface1 - static bool triedIDXGraphicsAnalysis = false; - - if (!triedIDXGraphicsAnalysis) - { - IDXGraphicsAnalysis *graphicsAnalysis = nullptr; - - HRESULT result = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); - if (SUCCEEDED(result)) - { - underCapture = (graphicsAnalysis != nullptr); - } - - SafeRelease(graphicsAnalysis); - triedIDXGraphicsAnalysis = true; - } - - return underCapture; -#else - // We can't detect GetStatus() on release WinRT 8.1 builds, so always return true. - return true; -#endif // (NTDDI_VERSION == NTDDI_WIN10) or _DEBUG #else // We can't detect GetStatus() on desktop ANGLE builds so always return true. return true; @@ -141,14 +101,13 @@ void DebugAnnotator11::initializeDevice() 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); + hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, + D3D11_SDK_VERSION, &device, nullptr, &context); ASSERT(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context); ASSERT(mUserDefinedAnnotation != nullptr); -#endif mInitialized = true; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h index d1a0f7fd2e..62662c49ae 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -9,14 +9,12 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ -#include "common/debug.h" - -struct ID3DUserDefinedAnnotation; +#include "libANGLE/LoggingAnnotator.h" namespace rx { -class DebugAnnotator11 : public gl::DebugAnnotator +class DebugAnnotator11 : public angle::LoggingAnnotator { public: DebugAnnotator11(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp index 53fac65f2a..082f28d794 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -4,7 +4,8 @@ // found in the LICENSE file. // -// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. +// Fence11.cpp: Defines the rx::FenceNV11 and rx::Sync11 classes which implement +// rx::FenceNVImpl and rx::SyncImpl. #include "libANGLE/renderer/d3d/d3d11/Fence11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" @@ -14,28 +15,30 @@ namespace rx { +static const int kDeviceLostCheckPeriod = 64; + // // Template helpers for set and test operations. // -template<class FenceClass> +template <class FenceClass> gl::Error FenceSetHelper(FenceClass *fence) { if (!fence->mQuery) { D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; + 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); + return gl::OutOfMemory() << "Failed to create event query, " << gl::FmtHR(result); } } fence->mRenderer->getDeviceContext()->End(fence->mQuery); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } template <class FenceClass> @@ -44,30 +47,24 @@ gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean ASSERT(fence->mQuery); UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); - HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); + HRESULT result = + fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, nullptr, 0, getDataFlags); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); - } - else if (fence->mRenderer->isDeviceLost()) - { - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + return gl::OutOfMemory() << "Failed to get query data, " << gl::FmtHR(result); } ASSERT(result == S_OK || result == S_FALSE); *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // // FenceNV11 // -FenceNV11::FenceNV11(Renderer11 *renderer) - : FenceNVImpl(), - mRenderer(renderer), - mQuery(NULL) +FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr) { } @@ -89,22 +86,26 @@ gl::Error FenceNV11::test(GLboolean *outFinished) gl::Error FenceNV11::finish() { GLboolean finished = GL_FALSE; + + int loopCount = 0; while (finished != GL_TRUE) { - gl::Error error = FenceTestHelper(this, true, &finished); - if (error.isError()) + loopCount++; + ANGLE_TRY(FenceTestHelper(this, true, &finished)); + + if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost()) { - return error; + return gl::OutOfMemory() << "Device was lost while querying result of an event query."; } ScheduleYield(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // -// FenceSync11 +// Sync11 // // Important note on accurate timers in Windows: @@ -118,38 +119,34 @@ gl::Error FenceNV11::finish() // 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) +Sync11::Sync11(Renderer11 *renderer) : SyncImpl(), mRenderer(renderer), mQuery(nullptr) { LARGE_INTEGER counterFreqency = {}; - BOOL success = QueryPerformanceFrequency(&counterFreqency); - UNUSED_ASSERTION_VARIABLE(success); + BOOL success = QueryPerformanceFrequency(&counterFreqency); ASSERT(success); mCounterFrequency = counterFreqency.QuadPart; } -FenceSync11::~FenceSync11() +Sync11::~Sync11() { SafeRelease(mQuery); } -gl::Error FenceSync11::set(GLenum condition, GLbitfield flags) +gl::Error Sync11::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) +gl::Error Sync11::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); + gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); if (error.isError()) { *outResult = GL_WAIT_FAILED; @@ -159,28 +156,34 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou if (result == GL_TRUE) { *outResult = GL_ALREADY_SIGNALED; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } if (timeout == 0) { *outResult = GL_TIMEOUT_EXPIRED; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } LARGE_INTEGER currentCounter = {}; - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); + BOOL success = QueryPerformanceCounter(¤tCounter); ASSERT(success); - LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll); - LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout / 1000000000ull); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + // Extremely unlikely, but if mCounterFrequency is large enough, endCounter can wrap + if (endCounter < currentCounter.QuadPart) + { + endCounter = MAXLONGLONG; + } + + int loopCount = 0; while (currentCounter.QuadPart < endCounter && !result) { + loopCount++; ScheduleYield(); success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); ASSERT(success); error = FenceTestHelper(this, flushCommandBuffer, &result); @@ -189,6 +192,12 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou *outResult = GL_WAIT_FAILED; return error; } + + if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost()) + { + *outResult = GL_WAIT_FAILED; + return gl::OutOfMemory() << "Device was lost while querying result of an event query."; + } } if (currentCounter.QuadPart >= endCounter) @@ -200,32 +209,32 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou *outResult = GL_CONDITION_SATISFIED; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) +gl::Error Sync11::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); + // 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::NoError(); } -gl::Error FenceSync11::getStatus(GLint *outResult) +gl::Error Sync11::getStatus(GLint *outResult) { GLboolean result = GL_FALSE; - gl::Error error = FenceTestHelper(this, false, &result); + 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. + // 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); + return gl::NoError(); } -} // namespace rx +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h index 595978885b..4168df5365 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -4,13 +4,14 @@ // found in the LICENSE file. // -// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. +// Fence11.h: Defines the rx::FenceNV11 and rx::Sync11 classes which implement rx::FenceNVImpl +// and rx::SyncImpl. #ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ #include "libANGLE/renderer/FenceNVImpl.h" -#include "libANGLE/renderer/FenceSyncImpl.h" +#include "libANGLE/renderer/SyncImpl.h" namespace rx { @@ -34,11 +35,11 @@ class FenceNV11 : public FenceNVImpl ID3D11Query *mQuery; }; -class FenceSync11 : public FenceSyncImpl +class Sync11 : public SyncImpl { public: - explicit FenceSync11(Renderer11 *renderer); - ~FenceSync11() override; + explicit Sync11(Renderer11 *renderer); + ~Sync11() override; gl::Error set(GLenum condition, GLbitfield flags) override; gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp index 186a035902..02326d7b50 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -8,94 +8,119 @@ #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "common/bitset_utils.h" #include "common/debug.h" +#include "libANGLE/Context.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/TextureD3D.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/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.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" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +using namespace angle; namespace rx { -Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer) - : FramebufferD3D(data, renderer), mRenderer(renderer) +namespace { - ASSERT(mRenderer != nullptr); -} - -Framebuffer11::~Framebuffer11() +gl::Error MarkAttachmentsDirty(const gl::Context *context, + const gl::FramebufferAttachment *attachment) { -} - -static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment) -{ - if (attachment && attachment->type() == GL_TEXTURE) + if (attachment->type() == GL_TEXTURE) { gl::Texture *texture = attachment->getTexture(); TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); TextureStorage *texStorage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&texStorage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage)); if (texStorage) { TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage); ASSERT(texStorage11); - texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel()); + texStorage11->markLevelDirty(attachment->mipLevel()); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidateSwizzles() const +void UpdateCachedRenderTarget(const gl::Context *context, + const gl::FramebufferAttachment *attachment, + RenderTarget11 *&cachedRenderTarget, + OnRenderTargetDirtyBinding *channelBinding) { - for (const auto &colorAttachment : mData.getColorAttachments()) + RenderTarget11 *newRenderTarget = nullptr; + if (attachment) { - if (colorAttachment.isAttached()) + // TODO(jmadill): Don't swallow this error. + gl::Error error = attachment->getRenderTarget(context, &newRenderTarget); + if (error.isError()) { - gl::Error error = InvalidateAttachmentSwizzles(&colorAttachment); - if (error.isError()) - { - return error; - } + ERR() << "Internal rendertarget error: " << error; } } + if (newRenderTarget != cachedRenderTarget) + { + OnRenderTargetDirtyChannel *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.emplace_back(this, colorIndex); + } +} - gl::Error error = InvalidateAttachmentSwizzles(mData.getDepthAttachment()); - if (error.isError()) +Framebuffer11::~Framebuffer11() +{ +} + +gl::Error Framebuffer11::markAttachmentsDirty(const gl::Context *context) const +{ + const auto &colorAttachments = mState.getColorAttachments(); + for (size_t drawBuffer : mState.getEnabledDrawBuffers()) { - return error; + const gl::FramebufferAttachment &colorAttachment = colorAttachments[drawBuffer]; + ASSERT(colorAttachment.isAttached()); + ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment)); } - error = InvalidateAttachmentSwizzles(mData.getStencilAttachment()); - if (error.isError()) + const gl::FramebufferAttachment *dsAttachment = mState.getDepthOrStencilAttachment(); + if (dsAttachment) { - return error; + ANGLE_TRY(MarkAttachmentsDirty(context, dsAttachment)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams) +gl::Error Framebuffer11::clearImpl(const gl::Context *context, const ClearParameters &clearParams) { Clear11 *clearer = mRenderer->getClearer(); - gl::Error error(GL_NO_ERROR); - const gl::FramebufferAttachment *colorAttachment = mData.getFirstColorAttachment(); + const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment(); if (clearParams.scissorEnabled == true && colorAttachment != nullptr && UsePresentPathFast(mRenderer, colorAttachment)) { @@ -107,46 +132,43 @@ gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clea presentPathFastClearParams.scissor.y = framebufferSize.height - presentPathFastClearParams.scissor.y - presentPathFastClearParams.scissor.height; - error = clearer->clearFramebuffer(presentPathFastClearParams, mData); + ANGLE_TRY(clearer->clearFramebuffer(context, presentPathFastClearParams, mState)); } else { - error = clearer->clearFramebuffer(clearParams, mData); + ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState)); } - if (error.isError()) - { - return error; - } - - error = invalidateSwizzles(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(markAttachmentsDirty(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments) +gl::Error Framebuffer11::invalidate(const gl::Context *context, + size_t count, + const GLenum *attachments) { - return invalidateBase(count, attachments, false); + return invalidateBase(context, count, attachments, false); } -gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments) +gl::Error Framebuffer11::discard(const gl::Context *context, + size_t count, + const GLenum *attachments) { - return invalidateBase(count, attachments, true); + return invalidateBase(context, count, attachments, true); } -gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const +gl::Error Framebuffer11::invalidateBase(const gl::Context *context, + size_t count, + const GLenum *attachments, + bool useEXTBehavior) const { -#if defined(ANGLE_ENABLE_D3D11_1) ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); if (!deviceContext1) { // DiscardView() is only supported on ID3D11DeviceContext1 - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool foundDepth = false; @@ -175,37 +197,14 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) || (attachments[i] == GL_COLOR)); - RenderTarget11 *renderTarget = nullptr; - ID3D11View *colorView = nullptr; - gl::Error error(GL_NO_ERROR); - size_t colorAttachmentID = 0; - - if (attachments[i] == GL_COLOR) - { - colorAttachmentID = 0; - } - else + size_t colorIndex = + (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0)); + const gl::FramebufferAttachment *colorAttachment = + mState.getColorAttachment(colorIndex); + if (colorAttachment) { - colorAttachmentID = attachments[i] - GL_COLOR_ATTACHMENT0; + ANGLE_TRY(invalidateAttachment(context, colorAttachment)); } - - if (mData.getColorAttachment(static_cast<unsigned int>(colorAttachmentID))) - { - error = mData.getColorAttachment(static_cast<unsigned int>(colorAttachmentID)) - ->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - colorView = renderTarget->getRenderTargetView(); - - if (colorView != nullptr) - { - deviceContext1->DiscardView(colorView); - } - } - break; } } @@ -222,7 +221,7 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, discardDepth = foundDepth; // Don't bother discarding the stencil buffer if the depth buffer will already do it - discardStencil = foundStencil && (!discardDepth || mData.getDepthAttachment() == nullptr); + discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr); } else { @@ -230,94 +229,86 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, // 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 && (mData.getStencilAttachment() == nullptr)); - discardStencil = (foundStencil && (mData.getDepthAttachment() == nullptr)); + discardDepth = (foundDepth && foundStencil) || + (foundDepth && (mState.getStencilAttachment() == nullptr)); + discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr)); } - if (discardDepth && mData.getDepthAttachment()) + if (discardDepth && mState.getDepthAttachment()) { - RenderTarget11 *renderTarget = nullptr; - ID3D11View *depthView = nullptr; - gl::Error error(GL_NO_ERROR); - - error = mData.getDepthAttachment()->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - depthView = renderTarget->getDepthStencilView(); - - if (depthView != nullptr) - { - deviceContext1->DiscardView(depthView); - } + ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment())); } - if (discardStencil && mData.getStencilAttachment()) + if (discardStencil && mState.getStencilAttachment()) { - RenderTarget11 *renderTarget = nullptr; - ID3D11View *stencilView = nullptr; - gl::Error error(GL_NO_ERROR); - - error = mData.getStencilAttachment()->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - stencilView = renderTarget->getDepthStencilView(); - - if (stencilView != nullptr) - { - deviceContext1->DiscardView(stencilView); - } + ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment())); } -#endif // ANGLE_ENABLE_D3D11_1 - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +gl::Error Framebuffer11::invalidateSub(const gl::Context *context, + size_t, + const GLenum *, + const gl::Rectangle &) { // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED() - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area, +gl::Error Framebuffer11::invalidateAttachment(const gl::Context *context, + const gl::FramebufferAttachment *attachment) const +{ + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + ASSERT(deviceContext1); + ASSERT(attachment && attachment->isAttached()); + + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment->getRenderTarget(context, &renderTarget)); + const auto &rtv = renderTarget->getRenderTargetView(); + + if (rtv.valid()) + { + deviceContext1->DiscardView(rtv.get()); + } + + return gl::NoError(); +} + +gl::Error Framebuffer11::readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const + uint8_t *pixels) { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); ASSERT(readAttachment); - gl::Buffer *packBuffer = pack.pixelBuffer.get(); + gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack); if (packBuffer != nullptr) { - if (pack.rowLength != 0 || pack.skipRows != 0 || pack.skipPixels != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, - "Unimplemented pixel store parameters in readPixelsImpl"); - } - Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer); PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack, - reinterpret_cast<ptrdiff_t>(pixels)); + packBuffer, reinterpret_cast<ptrdiff_t>(pixels)); - return packBufferStorage->packPixels(*readAttachment, packParams); + return packBufferStorage->packPixels(context, *readAttachment, packParams); } - return mRenderer->readFromAttachment(*readAttachment, area, format, type, + return mRenderer->readFromAttachment(context, *readAttachment, area, format, type, static_cast<GLuint>(outputPitch), pack, pixels); } -gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, - bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, - const gl::Framebuffer *sourceFramebuffer) +gl::Error Framebuffer11::blitImpl(const gl::Context *context, + 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) { @@ -325,15 +316,11 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang ASSERT(readBuffer); RenderTargetD3D *readRenderTarget = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget)); ASSERT(readRenderTarget); - const auto &colorAttachments = mData.getColorAttachments(); - const auto &drawBufferStates = mData.getDrawBufferStates(); + const auto &colorAttachments = mState.getColorAttachments(); + const auto &drawBufferStates = mState.getDrawBufferStates(); for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { @@ -343,11 +330,7 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang drawBufferStates[colorAttachment] != GL_NONE) { RenderTargetD3D *drawRenderTarget = nullptr; - error = drawBuffer.getRenderTarget(&drawRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(drawBuffer.getRenderTarget(context, &drawRenderTarget)); ASSERT(drawRenderTarget); const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer); @@ -368,13 +351,9 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang actualDestArea.height = -destArea.height; } - error = mRenderer->blitRenderbufferRect(actualSourceArea, actualDestArea, - readRenderTarget, drawRenderTarget, filter, - scissor, blitRenderTarget, false, false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->blitRenderbufferRect( + context, actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget, + filter, scissor, blitRenderTarget, false, false)); } } } @@ -385,46 +364,144 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang ASSERT(readBuffer); RenderTargetD3D *readRenderTarget = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget)); ASSERT(readRenderTarget); - const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); ASSERT(drawBuffer); RenderTargetD3D *drawRenderTarget = nullptr; - error = drawBuffer->getRenderTarget(&drawRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget)); ASSERT(drawRenderTarget); - error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor, - false, blitDepth, blitStencil); - if (error.isError()) + ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget, + drawRenderTarget, filter, scissor, false, + blitDepth, blitStencil)); + } + + ANGLE_TRY(markAttachmentsDirty(context)); + return gl::NoError(); +} + +GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget); + return renderTarget11->getFormatSet().format().fboImplementationInternalFormat; +} + +void Framebuffer11::updateColorRenderTarget(const gl::Context *context, size_t colorIndex) +{ + UpdateCachedRenderTarget(context, mState.getColorAttachment(colorIndex), + mCachedColorRenderTargets[colorIndex], + &mColorRenderTargetsDirty[colorIndex]); +} + +void Framebuffer11::updateDepthStencilRenderTarget(const gl::Context *context) +{ + UpdateCachedRenderTarget(context, mState.getDepthOrStencilAttachment(), + mCachedDepthStencilRenderTarget, &mDepthStencilRenderTargetDirty); +} + +void Framebuffer11::syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) +{ + const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits; + mInternalDirtyBits.reset(); + + for (auto dirtyBit : mergedDirtyBits) + { + switch (dirtyBit) { - return error; + case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: + case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: + updateDepthStencilRenderTarget(context); + break; + case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS: + case gl::Framebuffer::DIRTY_BIT_READ_BUFFER: + break; + case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS: + 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(context, colorIndex); + break; + } } } - gl::Error error = invalidateSwizzles(); - if (error.isError()) + // We should not have dirtied any additional state during our sync. + ASSERT(!mInternalDirtyBits.any()); + + FramebufferD3D::syncState(context, dirtyBits); + + // Call this last to allow the state manager to take advantage of the cached render targets. + mRenderer->getStateManager()->invalidateRenderTarget(); + + // Call this to syncViewport for framebuffer default parameters. + if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0) + { + mRenderer->getStateManager()->invalidateViewport(context); + } +} + +void Framebuffer11::signal(size_t channelID, const gl::Context *context) +{ + if (channelID == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) + { + // Stencil is redundant in this case. + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT); + mCachedDepthStencilRenderTarget = nullptr; + } + else { - return error; + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + channelID); + mCachedColorRenderTargets[channelID] = nullptr; } - return gl::Error(GL_NO_ERROR); + // Notify the context we need to re-validate the RenderTarget. + // TODO(jmadill): Check that we're the active draw framebuffer. + mRenderer->getStateManager()->invalidateRenderTarget(); } -GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +gl::Error Framebuffer11::getSamplePosition(size_t index, GLfloat *xy) const { - RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat()); - return dxgiFormatInfo.internalFormat; + const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment(); + ASSERT(attachment); + GLsizei sampleCount = attachment->getSamples(); + + d3d11_gl::GetSamplePosition(sampleCount, index, xy); + return gl::NoError(); +} + +bool Framebuffer11::hasAnyInternalDirtyBit() const +{ + return mInternalDirtyBits.any(); +} + +void Framebuffer11::syncInternalState(const gl::Context *context) +{ + syncState(context, gl::Framebuffer::DirtyBits()); } +RenderTarget11 *Framebuffer11::getFirstRenderTarget() const +{ + ASSERT(mInternalDirtyBits.none()); + for (auto *renderTarget : mCachedColorRenderTargets) + { + if (renderTarget) + { + return renderTarget; + } + } + + return mCachedDepthStencilRenderTarget; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h index c8a33ec7e5..afdda299b9 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -10,43 +10,93 @@ #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 +class Framebuffer11 : public FramebufferD3D, public OnRenderTargetDirtyReceiver { public: - Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer); - virtual ~Framebuffer11(); + Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer); + ~Framebuffer11() override; - 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; + gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override; + gl::Error invalidate(const gl::Context *context, + size_t count, + const GLenum *attachments) override; + gl::Error invalidateSub(const gl::Context *context, + size_t count, + const GLenum *attachments, + const gl::Rectangle &area) override; // Invalidate the cached swizzles of all bound texture attachments. - gl::Error invalidateSwizzles() const; + gl::Error markAttachmentsDirty(const gl::Context *context) const; + + void syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) override; + + const RenderTargetArray &getCachedColorRenderTargets() const + { + return mCachedColorRenderTargets; + } + const RenderTarget11 *getCachedDepthStencilRenderTarget() const + { + return mCachedDepthStencilRenderTarget; + } + + RenderTarget11 *getFirstRenderTarget() const; + + bool hasAnyInternalDirtyBit() const; + void syncInternalState(const gl::Context *context); + + void signal(size_t channelID, const gl::Context *context) override; + + gl::Error getSamplePosition(size_t index, GLfloat *xy) const override; private: - gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override; - gl::Error readPixelsImpl(const gl::Rectangle &area, + gl::Error readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const override; + uint8_t *pixels) override; - gl::Error blit(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 blitImpl(const gl::Context *context, + 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 invalidateBase(const gl::Context *context, + size_t count, + const GLenum *attachments, + bool useEXTBehavior) const; + gl::Error invalidateAttachment(const gl::Context *context, + const gl::FramebufferAttachment *attachment) const; GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + void updateColorRenderTarget(const gl::Context *context, size_t colorIndex); + void updateDepthStencilRenderTarget(const gl::Context *context); + Renderer11 *const mRenderer; + RenderTargetArray mCachedColorRenderTargets; + RenderTarget11 *mCachedDepthStencilRenderTarget; + + std::vector<OnRenderTargetDirtyBinding> mColorRenderTargetsDirty; + OnRenderTargetDirtyBinding mDepthStencilRenderTargetDirty; + + gl::Framebuffer::DirtyBits mInternalDirtyBits; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp index c52092d81e..bd921f1935 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -26,10 +26,10 @@ namespace rx Image11::Image11(Renderer11 *renderer) : mRenderer(renderer), mDXGIFormat(DXGI_FORMAT_UNKNOWN), - mStagingTexture(NULL), + mStagingTexture(), mStagingSubresource(0), mRecoverFromStorage(false), - mAssociatedStorage(NULL), + mAssociatedStorage(nullptr), mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), mRecoveredFromStorageCount(0) { @@ -41,55 +41,106 @@ Image11::~Image11() releaseStagingTexture(); } -gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src) +// static +gl::Error Image11::GenerateMipmap(const gl::Context *context, + 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()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); - ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); - D3D11_MAPPED_SUBRESOURCE destMapped; - gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped); + ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); + + D3D11_MAPPED_SUBRESOURCE srcMapped; + gl::Error error = src->map(context, 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(); +} + +// static +gl::Error Image11::CopyImage(const gl::Context *context, + Image11 *dest, + Image11 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const Renderer11DeviceCaps &rendererCaps) +{ + D3D11_MAPPED_SUBRESOURCE destMapped; + ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); + D3D11_MAPPED_SUBRESOURCE srcMapped; - error = src->map(D3D11_MAP_READ, &srcMapped); + gl::Error error = source->map(context, 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); + const auto &sourceFormat = + d3d11::Format::Get(source->getInternalFormat(), rendererCaps).format(); + GLuint sourcePixelBytes = + gl::GetSizedInternalFormatInfo(sourceFormat.fboImplementationInternalFormat).pixelBytes; + + GLenum destUnsizedFormat = gl::GetUnsizedFormat(dest->getInternalFormat()); + const auto &destFormat = d3d11::Format::Get(dest->getInternalFormat(), rendererCaps).format(); + const auto &destFormatInfo = + gl::GetSizedInternalFormatInfo(destFormat.fboImplementationInternalFormat); + GLuint destPixelBytes = destFormatInfo.pixelBytes; - dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), - sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, - destData, destMapped.RowPitch, destMapped.DepthPitch); + const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData) + + sourceRect.x * sourcePixelBytes + sourceRect.y * srcMapped.RowPitch; + uint8_t *destData = reinterpret_cast<uint8_t *>(destMapped.pData) + + destOffset.x * destPixelBytes + destOffset.y * destMapped.RowPitch; + + CopyImageCHROMIUM(sourceData, srcMapped.RowPitch, sourcePixelBytes, + sourceFormat.colorReadFunction, destData, destMapped.RowPitch, destPixelBytes, + destFormat.colorWriteFunction, destUnsizedFormat, + destFormatInfo.componentType, sourceRect.width, sourceRect.height, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); dest->unmap(); - src->unmap(); + source->unmap(); dest->markDirty(); - return gl::Error(GL_NO_ERROR); + 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) + // 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) AND robust resource initialization is not enabled then isDirty should + // still return false. + if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage) { const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); - const d3d11::TextureFormat formatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, deviceCaps); + const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps); if (formatInfo.dataInitializerFunction == nullptr) { return false; @@ -99,92 +150,69 @@ bool Image11::isDirty() const return mDirty; } -gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error Image11::copyToStorage(const gl::Context *context, + 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. + // 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. - gl::Error error = storage11->releaseAssociatedImage(index, this); - if (error.isError()) - { - return error; - } + // 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(context, index, this)); } - ID3D11Resource *stagingTexture = NULL; + const TextureHelper11 *stagingTexture = nullptr; unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } - - error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex)); + ANGLE_TRY(storage11->updateSubresourceLevel(context, *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; + mRecoverFromStorage = true; + mAssociatedStorage = storage11; mAssociatedImageIndex = index; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const +void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const { - return (mAssociatedStorage == textureStorage); + ASSERT(mAssociatedStorage == textureStorage); } -gl::Error Image11::recoverFromAssociatedStorage() +gl::Error Image11::recoverFromAssociatedStorage(const gl::Context *context) { if (mRecoverFromStorage) { - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } - - bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); + ANGLE_TRY(createStagingTexture()); - // 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); + mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this); - if (textureStorageCorrect) - { - // CopySubResource from the Storage to the Staging texture - gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); - error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); - if (error.isError()) - { - return error; - } - - mRecoveredFromStorageCount += 1; - } + // CopySubResource from the Storage to the Staging texture + gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); + ANGLE_TRY(mAssociatedStorage->copySubresourceLevel( + context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region)); + mRecoveredFromStorageCount += 1; // Reset all the recovery parameters, even if the texture storage association is broken. disassociateStorage(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::disassociateStorage() @@ -194,17 +222,18 @@ void Image11::disassociateStorage() // Make the texturestorage release the Image11 too mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); - mRecoverFromStorage = false; - mAssociatedStorage = NULL; + mRecoverFromStorage = false; + mAssociatedStorage = nullptr; mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); } } -bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) +bool Image11::redefine(GLenum target, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { - if (mWidth != size.width || - mHeight != size.height || - mInternalFormat != internalformat || + if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat || forceRelease) { // End the association with the TextureStorage, since that data will be out of date. @@ -212,19 +241,20 @@ bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents & disassociateStorage(); mRecoveredFromStorageCount = 0; - mWidth = size.width; - mHeight = size.height; - mDepth = size.depth; + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; mInternalFormat = internalformat; - mTarget = target; + mTarget = target; // compute the d3d format that will be used - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &formatInfo = + d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps()); mDXGIFormat = formatInfo.texFormat; mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); releaseStagingTexture(); - mDirty = (formatInfo.dataInitializerFunction != NULL); + mDirty = (formatInfo.dataInitializerFunction != nullptr); return true; } @@ -241,119 +271,125 @@ DXGI_FORMAT Image11::getDXGIFormat() const return mDXGIFormat; } -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// 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 type, const void *input) +gl::Error Image11::loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) { - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch( - type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); - GLsizei inputSkipBytes = formatInfo.computeSkipPixels( - inputRowPitch, inputDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type).loadFunction; + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLuint inputRowPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength), + inputRowPitch); + GLuint inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch), + inputDepthPitch); + GLuint inputSkipBytes = 0; + ANGLE_TRY_RESULT( + formatInfo.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()(type).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); - uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch)); + 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::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) +gl::Error Image11::loadCompressedData(const gl::Context *context, + const gl::Box &area, + const void *input) { - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); - GLsizei inputDepthPitch = - formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; - GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; + 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::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE).loadFunction; + const d3d11::Format &d3dFormatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = + d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(map(context, 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); + 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); + loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t *>(input), + inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, + mappedImage.DepthPitch); unmap(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) +gl::Error Image11::copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) { TextureStorage11 *storage11 = GetAs<TextureStorage11>(source); - ID3D11Resource *resource = nullptr; - gl::Error error = storage11->getResource(&resource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *textureHelper = nullptr; + ANGLE_TRY(storage11->getResource(context, &textureHelper)); - UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(resource); + UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); - return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex); + return copyWithoutConversion(gl::Offset(), sourceBox, *textureHelper, subresourceIndex); } -gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, +gl::Error Image11::copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *sourceFBO) { const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer(); ASSERT(srcAttachment); - const auto &d3d11Format = d3d11::GetTextureFormatInfo(srcAttachment->getInternalFormat(), - mRenderer->getRenderer11DeviceCaps()); + GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat; + const auto &d3d11Format = + d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps()); - if (d3d11Format.texFormat == mDXGIFormat) + if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat) { - RenderTargetD3D *renderTarget = nullptr; - gl::Error error = srcAttachment->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); - ASSERT(rt11->getTexture()); + RenderTarget11 *rt11 = nullptr; + ANGLE_TRY(srcAttachment->getRenderTarget(context, &rt11)); + ASSERT(rt11->getTexture().get()); - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + TextureHelper11 textureHelper = rt11->getTexture(); unsigned int sourceSubResource = rt11->getSubresourceIndex(); gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); @@ -363,25 +399,47 @@ gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, // This format requires conversion, so we must copy the texture to staging and manually convert // via readPixels D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); // determine the offset coordinate into the destination buffer - const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + 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 &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(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; + angle::MemoryBuffer *memoryBuffer = nullptr; + error = mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer); + + if (!error.isError()) + { + GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width; - error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, formatInfo.format, - formatInfo.type, mappedImage.RowPitch, - gl::PixelPackState(), dataOffset); + error = mRenderer->readFromAttachment( + context, *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( + context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type, + mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + } unmap(); mDirty = true; @@ -395,26 +453,23 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, UINT sourceSubResource) { // No conversion needed-- use copyback fastpath - ID3D11Resource *stagingTexture = nullptr; + const TextureHelper11 *stagingTexture = nullptr; unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } + 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); + 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; - if (needResolve) + if (textureHelper.is2D() && textureHelper.getSampleCount() > 1) { D3D11_TEXTURE2D_DESC resolveDesc; resolveDesc.Width = extents.width; @@ -429,80 +484,57 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, 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; + d3d11::Texture2D resolveTex; + ANGLE_TRY(mRenderer->allocateResource(resolveDesc, &resolveTex)); - deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(), + deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(), sourceSubResource, textureHelper.getFormat()); - subresourceAfterResolve = 0; + + deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, + destOffset.x, destOffset.y, destOffset.z, + resolveTex.get(), 0, &srcBox); } 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); + deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, + destOffset.x, destOffset.y, destOffset.z, + textureHelper.get(), sourceSubResource, &srcBox); } mDirty = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex) +gl::Error Image11::getStagingTexture(const TextureHelper11 **outStagingTexture, + unsigned int *outSubresourceIndex) { - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(createStagingTexture()); - *outStagingTexture = mStagingTexture; + *outStagingTexture = &mStagingTexture; *outSubresourceIndex = mStagingSubresource; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::releaseStagingTexture() { - SafeRelease(mStagingTexture); + mStagingTexture.reset(); } gl::Error Image11::createStagingTexture() { - if (mStagingTexture) + if (mStagingTexture.valid()) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + const auto &formatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - int lodOffset = 1; - GLsizei width = mWidth; + int lodOffset = 1; + GLsizei width = mWidth; GLsizei height = mHeight; // adjust size if needed for compressed textures @@ -510,80 +542,69 @@ gl::Error Image11::createStagingTexture() 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.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; + desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { std::vector<D3D11_SUBRESOURCE_DATA> initialData; std::vector<std::vector<BYTE>> textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, mDepth, - lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, mDepth, lodOffset + 1, &initialData, + &textureData); - result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + ANGLE_TRY( + mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture)); } else { - result = device->CreateTexture3D(&desc, NULL, &newTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture)); } - 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; + mStagingTexture.setDebugName("Image11::StagingTexture3D"); mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); } - else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + 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.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; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { std::vector<D3D11_SUBRESOURCE_DATA> initialData; std::vector<std::vector<BYTE>> textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 1, - lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, 1, lodOffset + 1, &initialData, + &textureData); - result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + ANGLE_TRY( + mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture)); } else { - result = device->CreateTexture2D(&desc, NULL, &newTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture)); } - 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; + mStagingTexture.setDebugName("Image11::StagingTexture2D"); mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); } else @@ -592,30 +613,22 @@ gl::Error Image11::createStagingTexture() } mDirty = false; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +gl::Error Image11::map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. - gl::Error error = recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(recoverFromAssociatedStorage(context)); - ID3D11Resource *stagingTexture = NULL; - unsigned int subresourceIndex = 0; - error = getStagingTexture(&stagingTexture, &subresourceIndex); - if (error.isError()) - { - return error; - } + const TextureHelper11 *stagingTexture = nullptr; + unsigned int subresourceIndex = 0; + ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex)); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ASSERT(mStagingTexture); - HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); + ASSERT(stagingTexture && stagingTexture->valid()); + HRESULT result = deviceContext->Map(stagingTexture->get(), subresourceIndex, mapType, 0, map); if (FAILED(result)) { @@ -624,20 +637,20 @@ gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { mRenderer->notifyDeviceLost(); } - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map staging texture, " << gl::FmtHR(result); } mDirty = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::unmap() { - if (mStagingTexture) + if (mStagingTexture.valid()) { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); + deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h index a5fcec84f8..584d231b37 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -10,10 +10,10 @@ #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" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -25,37 +25,63 @@ 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); - - virtual bool isDirty() const; - - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + ~Image11() override; + + static gl::Error GenerateMipmap(const gl::Context *context, + Image11 *dest, + Image11 *src, + const Renderer11DeviceCaps &rendererCaps); + static gl::Error CopyImage(const gl::Context *context, + Image11 *dest, + Image11 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const Renderer11DeviceCaps &rendererCaps); + + bool isDirty() const override; + + gl::Error copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) override; bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; DXGI_FORMAT getDXGIFormat() const; - virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); - virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - - gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; - gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + gl::Error loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) override; + gl::Error loadCompressedData(const gl::Context *context, + const gl::Box &area, + const void *input) override; + + gl::Error copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) override; - gl::Error recoverFromAssociatedStorage(); - bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + gl::Error recoverFromAssociatedStorage(const gl::Context *context); + void verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const; void disassociateStorage(); protected: - gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + gl::Error map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); void unmap(); private: @@ -64,14 +90,15 @@ class Image11 : public ImageD3D const TextureHelper11 &textureHelper, UINT sourceSubResource); - gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); + gl::Error getStagingTexture(const TextureHelper11 **outStagingTexture, + unsigned int *outSubresourceIndex); gl::Error createStagingTexture(); void releaseStagingTexture(); Renderer11 *mRenderer; DXGI_FORMAT mDXGIFormat; - ID3D11Resource *mStagingTexture; + TextureHelper11 mStagingTexture; unsigned int mStagingSubresource; bool mRecoverFromStorage; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp index a5e78a245d..a79fb71f71 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -14,28 +14,23 @@ namespace rx { -IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) + : mRenderer(renderer), mBuffer(), mBufferSize(0), mIndexType(GL_NONE), mDynamicUsage(false) { - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; } IndexBuffer11::~IndexBuffer11() { - SafeRelease(mBuffer); } gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { - SafeRelease(mBuffer); + mBuffer.reset(); updateSerial(); if (bufferSize > 0) { - ID3D11Device* dxDevice = mRenderer->getDevice(); - D3D11_BUFFER_DESC bufferDesc; bufferDesc.ByteWidth = bufferSize; bufferDesc.Usage = D3D11_USAGE_DYNAMIC; @@ -44,19 +39,15 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b 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); - } + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer)); if (dynamic) { - d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)"); + mBuffer.setDebugName("IndexBuffer11 (dynamic)"); } else { - d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)"); + mBuffer.setDebugName("IndexBuffer11 (static)"); } } @@ -64,45 +55,46 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b mIndexType = indexType; mDynamicUsage = dynamic; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "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."); + return gl::OutOfMemory() << "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); + HRESULT result = + dxContext->Map(mBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result); } *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBuffer11::unmapBuffer() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return gl::Error(GL_NO_ERROR); + dxContext->Unmap(mBuffer.get(), 0); + return gl::NoError(); } GLenum IndexBuffer11::getIndexType() const @@ -123,29 +115,29 @@ gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } gl::Error IndexBuffer11::discard() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "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); + HRESULT result = dxContext->Map(mBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result); } - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } DXGI_FORMAT IndexBuffer11::getIndexFormat() const @@ -159,9 +151,9 @@ DXGI_FORMAT IndexBuffer11::getIndexFormat() const } } -ID3D11Buffer *IndexBuffer11::getBuffer() const +const d3d11::Buffer &IndexBuffer11::getBuffer() const { return mBuffer; } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h index e730377e00..7b5d744c02 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h @@ -10,6 +10,7 @@ #define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ #include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -19,31 +20,31 @@ class IndexBuffer11 : public IndexBuffer { public: explicit IndexBuffer11(Renderer11 *const renderer); - virtual ~IndexBuffer11(); + ~IndexBuffer11() override; - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) override; - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual gl::Error unmapBuffer(); + gl::Error mapBuffer(unsigned int offset, unsigned int size, void **outMappedMemory) override; + gl::Error unmapBuffer() override; - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + GLenum getIndexType() const override; + unsigned int getBufferSize() const override; + gl::Error setSize(unsigned int bufferSize, GLenum indexType) override; - virtual gl::Error discard(); + gl::Error discard() override; DXGI_FORMAT getIndexFormat() const; - ID3D11Buffer *getBuffer() const; + const d3d11::Buffer &getBuffer() const; private: Renderer11 *const mRenderer; - ID3D11Buffer *mBuffer; + d3d11::Buffer mBuffer; unsigned int mBufferSize; GLenum mIndexType; bool mDynamicUsage; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp index 3a6d797ea6..a238f97b08 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -9,17 +9,22 @@ #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "common/bitset_utils.h" #include "common/utilities.h" +#include "libANGLE/Context.h" #include "libANGLE/Program.h" +#include "libANGLE/VertexArray.h" #include "libANGLE/VertexAttribute.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/Context11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "third_party/murmurhash/MurmurHash3.h" namespace rx { @@ -32,24 +37,7 @@ size_t GetReservedBufferCount(bool usesPointSpriteEmulation) return usesPointSpriteEmulation ? 1 : 0; } -gl::InputLayout GetInputLayout(const SortedAttribArray &translatedAttributes, size_t attributeCount) -{ - gl::InputLayout inputLayout(attributeCount, gl::VERTEX_FORMAT_INVALID); - - for (size_t attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex) - { - const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex]; - - if (translatedAttribute->active) - { - inputLayout[attributeIndex] = gl::GetVertexFormatType( - *translatedAttribute->attribute, translatedAttribute->currentValueType); - } - } - return inputLayout; -} - -GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, int index) +GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, size_t index) { // Count matrices differently for (const sh::Attribute &attrib : shaderAttributes) @@ -61,8 +49,9 @@ GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, GLenum transposedType = gl::TransposeMatrixType(attrib.type); int rows = gl::VariableRowCount(transposedType); + int intIndex = static_cast<int>(index); - if (index >= attrib.location && index < attrib.location + rows) + if (intIndex >= attrib.location && intIndex < attrib.location + rows) { return transposedType; } @@ -72,8 +61,6 @@ GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, return GL_NONE; } -const unsigned int kDefaultCacheSize = 1024; - struct PackedAttribute { uint8_t attribType; @@ -82,26 +69,18 @@ struct PackedAttribute uint8_t divisor; }; -Optional<size_t> FindFirstNonInstanced(const SortedAttribArray &sortedAttributes, size_t maxIndex) -{ - for (size_t index = 0; index < maxIndex; ++index) - { - if (sortedAttributes[index]->divisor == 0) - { - return Optional<size_t>(index); - } - } +} // anonymous namespace - return Optional<size_t>::Invalid(); +PackedAttributeLayout::PackedAttributeLayout() : numAttributes(0), flags(0), attributeData({}) +{ } -} // anonymous namespace +PackedAttributeLayout::PackedAttributeLayout(const PackedAttributeLayout &other) = default; -void InputLayoutCache::PackedAttributeLayout::addAttributeData( - GLenum glType, - UINT semanticIndex, - gl::VertexFormatType vertexFormatType, - unsigned int divisor) +void PackedAttributeLayout::addAttributeData(GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor) { gl::AttributeType attribType = gl::GetAttributeType(glType); @@ -121,139 +100,58 @@ void InputLayoutCache::PackedAttributeLayout::addAttributeData( attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib); } -bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const +bool 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; + return (numAttributes == other.numAttributes) && (flags == other.flags) && + (attributeData == other.attributeData); } -InputLayoutCache::InputLayoutCache() : mUnsortedAttributesCount(0), mCacheSize(kDefaultCacheSize) +InputLayoutCache::InputLayoutCache() + : mLayoutCache(kDefaultCacheSize * 2), mPointSpriteVertexBuffer(), mPointSpriteIndexBuffer() { - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = static_cast<UINT>(-1); - mCurrentVertexOffsets[i] = static_cast<UINT>(-1); - } - mPointSpriteVertexBuffer = NULL; - mPointSpriteIndexBuffer = NULL; } 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 = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = static_cast<UINT>(-1); - mCurrentVertexOffsets[i] = static_cast<UINT>(-1); - } - mUnsortedAttributesCount = 0; + mLayoutCache.Clear(); + mPointSpriteVertexBuffer.reset(); + mPointSpriteIndexBuffer.reset(); } gl::Error InputLayoutCache::applyVertexBuffers( - const std::vector<TranslatedAttribute> &unsortedAttributes, + const gl::Context *context, + const std::vector<const TranslatedAttribute *> ¤tAttributes, GLenum mode, - gl::Program *program, - TranslatedIndexData *indexInfo, - GLsizei numIndicesPerInstance) + GLint start, + bool isIndexedRendering) { - ASSERT(mDevice && mDeviceContext); - + Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer(); + const gl::State &state = context->getGLState(); + auto *stateManager = renderer->getStateManager(); + gl::Program *program = state.getProgram(); ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); - SortedIndexArray sortedSemanticIndices; - mSortedAttributes.fill(nullptr); - mUnsortedAttributesCount = unsortedAttributes.size(); - - programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(), - mSortedAttributes.data()); - - // If we are using FL 9_3, make sure the first attribute is not instanced - if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !unsortedAttributes.empty()) - { - if (mSortedAttributes[0]->divisor > 0) - { - Optional<size_t> firstNonInstancedIndex = - FindFirstNonInstanced(mSortedAttributes, unsortedAttributes.size()); - if (firstNonInstancedIndex.valid()) - { - size_t index = firstNonInstancedIndex.value(); - std::swap(mSortedAttributes[0], mSortedAttributes[index]); - std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); - } - } - } - - gl::Error error = updateInputLayout(program, mode, mSortedAttributes, sortedSemanticIndices, - unsortedAttributes.size(), numIndicesPerInstance); - if (error.isError()) - { - return error; - } - - 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 = NULL; - UINT vertexStride = 0; - UINT vertexOffset = 0; + ID3D11Buffer *buffer = nullptr; + UINT vertexStride = 0; + UINT vertexOffset = 0; - const auto &attrib = *mSortedAttributes[attribIndex]; - - if (attribIndex < unsortedAttributes.size() && attrib.active) + if (attribIndex < currentAttributes.size()) { - VertexBuffer11 *vertexBuffer = GetAs<VertexBuffer11>(attrib.vertexBuffer); - Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr; + const auto &attrib = *currentAttributes[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 @@ -261,18 +159,18 @@ gl::Error InputLayoutCache::applyVertexBuffers( // on the number of points indicated by the index list or how many duplicates are found on the index list. if (bufferStorage == nullptr) { - buffer = vertexBuffer->getBuffer(); + ASSERT(attrib.vertexBuffer.get()); + buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get(); } - else if (instancedPointSpritesActive && (indexInfo != nullptr)) + else if (instancedPointSpritesActive && isIndexedRendering) { + VertexArray11 *vao11 = GetImplAs<VertexArray11>(state.getVertexArray()); + ASSERT(vao11->isCachedIndexInfoValid()); + TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo(); if (indexInfo->srcIndexData.srcBuffer != nullptr) { const uint8_t *bufferData = nullptr; - error = indexInfo->srcIndexData.srcBuffer->getData(&bufferData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(context, &bufferData)); ASSERT(bufferData != nullptr); ptrdiff_t offset = @@ -281,31 +179,24 @@ gl::Error InputLayoutCache::applyVertexBuffers( indexInfo->srcIndexData.srcIndices = bufferData + offset; } - buffer = bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, &attrib); + ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer( + context, &indexInfo->srcIndexData, attrib, start), + buffer); } else { - buffer = bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + ANGLE_TRY_RESULT( + bufferStorage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + buffer); } vertexStride = attrib.stride; - vertexOffset = attrib.offset; + 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; - } + stateManager->queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset); } // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs @@ -317,10 +208,9 @@ gl::Error InputLayoutCache::applyVertexBuffers( // handle missing vertex data and will TDR the system. if (programUsesInstancedPointSprites) { - HRESULT result = S_OK; const UINT pointSpriteVertexStride = sizeof(float) * 5; - if (!mPointSpriteVertexBuffer) + if (!mPointSpriteVertexBuffer.valid()) { static const float pointSpriteVertices[] = { @@ -342,25 +232,16 @@ gl::Error InputLayoutCache::applyVertexBuffers( 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); - } + ANGLE_TRY(renderer->allocateResource(vertexBufferDesc, &vertexBufferData, + &mPointSpriteVertexBuffer)); } - 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)); + UINT stride = instancedPointSpritesActive ? pointSpriteVertexStride : 0; + stateManager->queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0); - if (!mPointSpriteIndexBuffer) + if (!mPointSpriteIndexBuffer.valid()) { // Create an index buffer and set it for pointsprite rendering static const unsigned short pointSpriteIndices[] = @@ -377,12 +258,8 @@ gl::Error InputLayoutCache::applyVertexBuffers( 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); - } + ANGLE_TRY(renderer->allocateResource(indexBufferDesc, &indexBufferData, + &mPointSpriteIndexBuffer)); } if (instancedPointSpritesActive) @@ -391,51 +268,51 @@ gl::Error InputLayoutCache::applyVertexBuffers( // 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); + stateManager->setIndexBuffer(mPointSpriteIndexBuffer.get(), 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::Error(GL_NO_ERROR); + stateManager->applyVertexBufferChanges(); + return gl::NoError(); } -gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId) +gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation( + Renderer11 *renderer, + const std::vector<const TranslatedAttribute *> ¤tAttributes, + GLint startVertex, + GLsizei emulatedInstanceId) { + auto *stateManager = renderer->getStateManager(); + size_t reservedBuffers = GetReservedBufferCount(true); - for (size_t attribIndex = 0; attribIndex < mUnsortedAttributesCount; ++attribIndex) + for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex) { - const auto &attrib = *mSortedAttributes[attribIndex]; + const auto &attrib = *currentAttributes[attribIndex]; size_t bufferIndex = reservedBuffers + attribIndex; - if (attrib.active && attrib.divisor > 0) + if (attrib.divisor > 0) { - mCurrentVertexOffsets[bufferIndex] = - attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor)); + unsigned int offset = 0; + ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset); + offset += (attrib.stride * (emulatedInstanceId / attrib.divisor)); + stateManager->queueVertexOffsetChange(bufferIndex, offset); } } - mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers, - mCurrentVertexStrides, mCurrentVertexOffsets); - - return gl::Error(GL_NO_ERROR); + stateManager->applyVertexBufferChanges(); + return gl::NoError(); } -gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, - GLenum mode, - const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, - GLsizei numIndicesPerInstance) +gl::Error InputLayoutCache::updateInputLayout( + Renderer11 *renderer, + const gl::State &state, + const std::vector<const TranslatedAttribute *> ¤tAttributes, + GLenum mode, + const AttribIndexArray &sortedSemanticIndices, + const DrawCallVertexParams &vertexParams) { - const std::vector<sh::Attribute> &shaderAttributes = program->getAttributes(); + gl::Program *program = state.getProgram(); + const auto &shaderAttributes = program->getAttributes(); PackedAttributeLayout layout; ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); @@ -453,90 +330,70 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE; } - if (numIndicesPerInstance > 0) + if (vertexParams.instances() > 0) { layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE; } - const auto &semanticToLocation = programD3D->getAttributesByLayout(); + const auto &attribs = state.getVertexArray()->getVertexAttributes(); + const auto &bindings = state.getVertexArray()->getVertexBindings(); + const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics(); + int divisorMultiplier = program->usesMultiview() ? program->getNumViews() : 1; - for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + for (size_t attribIndex : program->getActiveAttribLocationsMask()) { - const auto &attrib = *sortedAttributes[attribIndex]; - int sortedIndex = sortedSemanticIndices[attribIndex]; - - if (!attrib.active) - continue; - - gl::VertexFormatType vertexFormatType = - gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType); - // 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, semanticToLocation[sortedIndex]); + GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex); - layout.addAttributeData(glslElementType, sortedIndex, vertexFormatType, attrib.divisor); + const auto &attrib = attribs[attribIndex]; + const auto &binding = bindings[attrib.bindingIndex]; + int d3dSemantic = locationToSemantic[attribIndex]; + + const auto ¤tValue = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type); + + layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, + binding.getDivisor() * divisorMultiplier); } - ID3D11InputLayout *inputLayout = nullptr; + const d3d11::InputLayout *inputLayout = nullptr; if (layout.numAttributes > 0 || layout.flags != 0) { - auto layoutMapIt = mLayoutMap.find(layout); - if (layoutMapIt != mLayoutMap.end()) + auto it = mLayoutCache.Get(layout); + if (it != mLayoutCache.end()) { - inputLayout = layoutMapIt->second; + inputLayout = &it->second; } else { - gl::Error error = - createInputLayout(sortedAttributes, sortedSemanticIndices, attribCount, mode, - program, numIndicesPerInstance, &inputLayout); - if (error.isError()) - { - return error; - } - if (mLayoutMap.size() >= mCacheSize) - { - TRACE("Overflowed the limit of %u input layouts, purging half the cache.", - mCacheSize); + angle::TrimCache(mLayoutCache.max_size() / 2, kGCLimit, "input layout", &mLayoutCache); - // 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); - } - } - } + d3d11::InputLayout newInputLayout; + ANGLE_TRY(createInputLayout(renderer, sortedSemanticIndices, currentAttributes, mode, + program, vertexParams, &newInputLayout)); - mLayoutMap[layout] = inputLayout; + auto insertIt = mLayoutCache.Put(layout, std::move(newInputLayout)); + inputLayout = &insertIt->second; } } - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - return gl::Error(GL_NO_ERROR); + renderer->getStateManager()->setInputLayout(inputLayout); + return gl::NoError(); } -gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, - GLenum mode, - gl::Program *program, - GLsizei numIndicesPerInstance, - ID3D11InputLayout **inputLayoutOut) +gl::Error InputLayoutCache::createInputLayout( + Renderer11 *renderer, + const AttribIndexArray &sortedSemanticIndices, + const std::vector<const TranslatedAttribute *> ¤tAttributes, + GLenum mode, + gl::Program *program, + const DrawCallVertexParams &vertexParams, + d3d11::InputLayout *inputLayoutOut) { ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + auto featureLevel = renderer->getRenderer11DeviceCaps().featureLevel; bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); @@ -544,20 +401,17 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt unsigned int inputElementCount = 0; std::array<D3D11_INPUT_ELEMENT_DESC, gl::MAX_VERTEX_ATTRIBS> inputElements; - for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex) { - const auto &attrib = *sortedAttributes[attribIndex]; + const auto &attrib = *currentAttributes[attribIndex]; const int sortedIndex = sortedSemanticIndices[attribIndex]; - if (!attrib.active) - continue; - 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); + const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); auto *inputElement = &inputElements[inputElementCount]; @@ -584,23 +438,28 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt // 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. + + GLsizei numIndicesPerInstance = 0; + if (vertexParams.instances() > 0) + { + // This may trigger an evaluation of the index range. + numIndicesPerInstance = vertexParams.vertexCount(); + } + for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex) { - if (sortedAttributes[elementIndex]->active) + // 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) { - // 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 && currentAttributes[elementIndex]->divisor > 0) { - inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; - inputElements[elementIndex].InstanceDataStepRate = 1; - if (numIndicesPerInstance > 0 && sortedAttributes[elementIndex]->divisor > 0) - { - inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance; - } + inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance; } - inputElements[elementIndex].InputSlot++; } + inputElements[elementIndex].InputSlot++; } inputElements[inputElementCount].SemanticName = "SPRITEPOSITION"; @@ -622,28 +481,23 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt inputElementCount++; } - const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attribCount); - ShaderExecutableD3D *shader = nullptr; - gl::Error error = - programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&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); - } + InputElementArray inputElementArray(inputElements.data(), inputElementCount); + ShaderData vertexShaderData(shader11->getFunction(), shader11->getLength()); - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(renderer->allocateResource(inputElementArray, &vertexShaderData, inputLayoutOut)); + return gl::NoError(); +} + +void InputLayoutCache::setCacheSize(size_t newCacheSize) +{ + // Forces a reset of the cache. + LayoutCache newCache(newCacheSize); + mLayoutCache.Swap(newCache); } } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h index e208ae3c64..8d7c7dd0f0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -20,12 +20,55 @@ #include "common/angleutils.h" #include "libANGLE/Constants.h" #include "libANGLE/Error.h" +#include "libANGLE/SizedMRUCache.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + +namespace rx +{ +class DrawCallVertexParams; +struct PackedAttributeLayout +{ + PackedAttributeLayout(); + PackedAttributeLayout(const PackedAttributeLayout &other); + + 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, + }; + + uint32_t numAttributes; + uint32_t flags; + std::array<uint32_t, gl::MAX_VERTEX_ATTRIBS> attributeData; +}; +} // namespace rx + +namespace std +{ +template <> +struct hash<rx::PackedAttributeLayout> +{ + size_t operator()(const rx::PackedAttributeLayout &value) const + { + return angle::ComputeGenericHash(value); + } +}; +} // namespace std namespace gl { class Program; -} +} // namespace gl namespace rx { @@ -33,91 +76,58 @@ struct TranslatedAttribute; struct TranslatedIndexData; struct SourceIndexData; class ProgramD3D; - -using SortedAttribArray = std::array<const TranslatedAttribute *, gl::MAX_VERTEX_ATTRIBS>; -using SortedIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>; +class Renderer11; class InputLayoutCache : angle::NonCopyable { public: InputLayoutCache(); - virtual ~InputLayoutCache(); + ~InputLayoutCache(); - void initialize(ID3D11Device *device, ID3D11DeviceContext *context); void clear(); - void markDirty(); - gl::Error applyVertexBuffers(const std::vector<TranslatedAttribute> &attributes, + gl::Error applyVertexBuffers(const gl::Context *context, + const std::vector<const TranslatedAttribute *> ¤tAttributes, GLenum mode, - gl::Program *program, - TranslatedIndexData *indexInfo, - GLsizei numIndicesPerInstance); + GLint start, + bool isIndexedRendering); - gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId); + gl::Error updateVertexOffsetsForPointSpritesEmulation( + Renderer11 *renderer, + const std::vector<const TranslatedAttribute *> ¤tAttributes, + 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]; - }; + void setCacheSize(size_t newCacheSize); - gl::Error updateInputLayout(gl::Program *program, + gl::Error updateInputLayout(Renderer11 *renderer, + const gl::State &state, + const std::vector<const TranslatedAttribute *> ¤tAttributes, GLenum mode, - const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, - GLsizei numIndicesPerInstance); - gl::Error createInputLayout(const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, + const AttribIndexArray &sortedSemanticIndices, + const DrawCallVertexParams &vertexParams); + + private: + gl::Error createInputLayout(Renderer11 *renderer, + const AttribIndexArray &sortedSemanticIndices, + const std::vector<const TranslatedAttribute *> ¤tAttributes, GLenum mode, gl::Program *program, - GLsizei numIndicesPerInstance, - ID3D11InputLayout **inputLayoutOut); - - std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap; + const DrawCallVertexParams &vertexParams, + d3d11::InputLayout *inputLayoutOut); - ID3D11InputLayout *mCurrentIL; - ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; - SortedAttribArray mSortedAttributes; - size_t mUnsortedAttributesCount; + // Starting cache size. + static constexpr size_t kDefaultCacheSize = 1024; - ID3D11Buffer *mPointSpriteVertexBuffer; - ID3D11Buffer *mPointSpriteIndexBuffer; + // The cache tries to clean up this many states at once. + static constexpr size_t kGCLimit = 128; - unsigned int mCacheSize; - unsigned long long mCounter; + using LayoutCache = angle::base::HashingMRUCache<PackedAttributeLayout, d3d11::InputLayout>; + LayoutCache mLayoutCache; - ID3D11Device *mDevice; - ID3D11DeviceContext *mDeviceContext; - D3D_FEATURE_LEVEL mFeatureLevel; + d3d11::Buffer mPointSpriteVertexBuffer; + d3d11::Buffer mPointSpriteIndexBuffer; }; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h deleted file mode 100644 index 612b06bb10..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +++ /dev/null @@ -1,97 +0,0 @@ -// -// 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. -// - -// NativeWindow.h: Defines NativeWindow, a class for managing and -// performing operations on an EGLNativeWindowType. -// It is used for HWND (Desktop Windows) and IInspectable objects -//(Windows Store Applications). - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ - -#include "common/debug.h" -#include "common/platform.h" - -#include <EGL/eglplatform.h> -#include "libANGLE/Config.h" - -// DXGISwapChain and DXGIFactory are typedef'd to specific required -// types. The HWND NativeWindow implementation requires IDXGISwapChain -// and IDXGIFactory and the Windows Store NativeWindow -// implementation requires IDXGISwapChain1 and IDXGIFactory2. -#if defined(ANGLE_ENABLE_WINDOWS_STORE) -typedef IDXGISwapChain1 DXGISwapChain; -typedef IDXGIFactory2 DXGIFactory; - -#include <wrl.h> -#include <wrl/wrappers/corewrappers.h> -#include <windows.applicationmodel.core.h> -#include <memory> - -namespace rx -{ -class InspectableNativeWindow; -} - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; - -#elif defined(ANGLE_ENABLE_D3D11) -typedef IDXGISwapChain DXGISwapChain; -typedef IDXGIFactory DXGIFactory; -#endif - -typedef interface IDCompositionDevice IDCompositionDevice; -typedef interface IDCompositionTarget IDCompositionTarget; -typedef interface IDCompositionVisual IDCompositionVisual; - -namespace rx -{ - -class NativeWindow -{ - public: - enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; - explicit NativeWindow(EGLNativeWindowType window, - const egl::Config *config, - bool directComposition); - - ~NativeWindow(); - bool initialize(); - bool getClientRect(LPRECT rect); - bool isIconic(); -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - RotationFlags rotationFlags() const; -#endif - static bool isValidNativeWindow(EGLNativeWindowType window); - -#if defined(ANGLE_ENABLE_D3D11) - HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, - DXGI_FORMAT format, UINT width, UINT height, - DXGISwapChain** swapChain); -#endif - - inline EGLNativeWindowType getNativeWindow() const { return mWindow; } - - void commitChange(); - - private: - EGLNativeWindowType mWindow; - - bool mDirectComposition; - IDCompositionDevice *mDevice; - IDCompositionTarget *mCompositionTarget; - IDCompositionVisual *mVisual; - const egl::Config *mConfig; -#if defined(ANGLE_ENABLE_WINDOWS_STORE) - std::shared_ptr<InspectableNativeWindow> mImpl; -#endif - -}; - -} - -#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h new file mode 100644 index 0000000000..ab234d4450 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.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. +// + +// 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) {} + + virtual HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) = 0; + virtual void commitChange() = 0; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp index dfc521f14f..7d7ecb0976 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -36,40 +36,25 @@ namespace rx PixelTransfer11::PixelTransfer11(Renderer11 *renderer) : mRenderer(renderer), mResourcesLoaded(false), - mBufferToTextureVS(NULL), - mBufferToTextureGS(NULL), - mParamsConstantBuffer(NULL), - mCopyRasterizerState(NULL), - mCopyDepthStencilState(NULL) + mBufferToTextureVS(), + mBufferToTextureGS(), + mParamsConstantBuffer(), + mCopyRasterizerState(), + mCopyDepthStencilState() { } 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::Error(GL_NO_ERROR); + 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; @@ -82,12 +67,7 @@ gl::Error PixelTransfer11::loadResources() 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); - } + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mCopyRasterizerState)); D3D11_DEPTH_STENCIL_DESC depthStencilDesc; depthStencilDesc.DepthEnable = true; @@ -105,12 +85,7 @@ gl::Error PixelTransfer11::loadResources() 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); - } + ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mCopyDepthStencilState)); D3D11_BUFFER_DESC constantBufferDesc = { 0 }; constantBufferDesc.ByteWidth = roundUp<UINT>(sizeof(CopyShaderParams), 32u); @@ -120,38 +95,23 @@ gl::Error PixelTransfer11::loadResources() 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"); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDesc, &mParamsConstantBuffer)); + mParamsConstantBuffer.setDebugName("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."); - } + ANGLE_TRY(mRenderer->allocateResource(ShaderData(g_VS_BufferToTexture), &mBufferToTextureVS)); + mBufferToTextureVS.setDebugName("BufferToTexture VS"); - 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(mRenderer->allocateResource(ShaderData(g_GS_BufferToTexture), &mBufferToTextureGS)); + mBufferToTextureGS.setDebugName("BufferToTexture GS"); - gl::Error error = buildShaderMap(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buildShaderMap()); StructZero(&mParamsData); mResourcesLoaded = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, @@ -162,7 +122,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons 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 bytesPerPixel = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes; unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment); unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); @@ -177,14 +137,15 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons 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) +gl::Error PixelTransfer11::copyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) { - gl::Error error = loadResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(loadResources()); gl::Extents destSize = destRenderTarget->getExtents(); @@ -192,114 +153,106 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac 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(); + const gl::Buffer &sourceBuffer = + *context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); - ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + const d3d11::PixelShader *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); + GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat); + const gl::InternalFormat &sourceglFormatInfo = + gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType); - const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &sourceFormatInfo = d3d11::Format::Get( + sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation()); - ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); - ASSERT(bufferSRV != NULL); + const d3d11::ShaderResourceView *bufferSRV = nullptr; + ANGLE_TRY_RESULT(bufferStorage11->getSRV(context, srvFormat), bufferSRV); + ASSERT(bufferSRV != nullptr); - ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); - ASSERT(textureRTV != NULL); + const d3d11::RenderTargetView &textureRTV = + GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV.valid()); CopyShaderParams shaderParams; - setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack, + offset, &shaderParams); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11Buffer *nullBuffer = NULL; - UINT zero = 0; - // Are we doing a 2D or 3D copy? - ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); - auto stateManager = mRenderer->getStateManager(); + const auto *geometryShader = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr); + StateManager11 *stateManager = mRenderer->getStateManager(); - deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); - deviceContext->GSSetShader(geometryShader, NULL, 0); - deviceContext->PSSetShader(pixelShader, NULL, 0); + stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader); stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); - deviceContext->IASetInputLayout(NULL); - deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); - deviceContext->RSSetState(mCopyRasterizerState); + stateManager->setSingleVertexBuffer(nullptr, 0, 0); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF); + stateManager->setRasterizerState(&mCopyRasterizerState); - mRenderer->setOneTimeRenderTarget(textureRTV); + stateManager->setRenderTarget(textureRTV.get(), nullptr); if (!StructEquals(mParamsData, shaderParams)) { - d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams); mParamsData = shaderParams; } - deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + stateManager->setVertexConstantBuffer(0, &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); + stateManager->setSimpleViewport(destSize); 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::Error(GL_NO_ERROR); + 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::Error(GL_NO_ERROR); + d3d11::PixelShader bufferToTextureFloat; + d3d11::PixelShader bufferToTextureInt; + d3d11::PixelShader bufferToTextureUint; + + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4F), &bufferToTextureFloat)); + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4I), &bufferToTextureInt)); + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4UI), &bufferToTextureUint)); + + bufferToTextureFloat.setDebugName("BufferToTexture RGBA ps"); + bufferToTextureInt.setDebugName("BufferToTexture RGBA-I ps"); + bufferToTextureUint.setDebugName("BufferToTexture RGBA-UI ps"); + + mBufferToTexturePSMap[GL_FLOAT] = std::move(bufferToTextureFloat); + mBufferToTexturePSMap[GL_INT] = std::move(bufferToTextureInt); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint); + + return gl::NoError(); } -ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const { - GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; + GLenum componentType = gl::GetSizedInternalFormatInfo(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); + return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h index 1672121ec7..a93544247e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h @@ -11,14 +11,14 @@ #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> +#include "common/platform.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + namespace gl { @@ -45,8 +45,13 @@ class PixelTransfer11 // 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); + gl::Error copyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea); private: @@ -68,22 +73,21 @@ class PixelTransfer11 gl::Error loadResources(); gl::Error buildShaderMap(); - ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + const d3d11::PixelShader *findBufferToTexturePS(GLenum internalFormat) const; Renderer11 *mRenderer; bool mResourcesLoaded; - std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap; - ID3D11VertexShader *mBufferToTextureVS; - ID3D11GeometryShader *mBufferToTextureGS; - ID3D11Buffer *mParamsConstantBuffer; + std::map<GLenum, d3d11::PixelShader> mBufferToTexturePSMap; + d3d11::VertexShader mBufferToTextureVS; + d3d11::GeometryShader mBufferToTextureGS; + d3d11::Buffer mParamsConstantBuffer; CopyShaderParams mParamsData; - ID3D11RasterizerState *mCopyRasterizerState; - ID3D11DepthStencilState *mCopyDepthStencilState; - + d3d11::RasterizerState mCopyRasterizerState; + d3d11::DepthStencilState mCopyDepthStencilState; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp new file mode 100644 index 0000000000..c9554431e5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp @@ -0,0 +1,24 @@ +// +// Copyright 2017 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. +// +// ProgramPipelineNULL.cpp: +// Implements the class methods for ProgramPipeline11. +// + +#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h" + +namespace rx +{ + +ProgramPipeline11::ProgramPipeline11(const gl::ProgramPipelineState &state) + : ProgramPipelineImpl(state) +{ +} + +ProgramPipeline11::~ProgramPipeline11() +{ +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h new file mode 100644 index 0000000000..cf838eec05 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h @@ -0,0 +1,27 @@ +// +// Copyright 2017 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. +// +// ProgramPipeline11.h: +// Defines the class interface for ProgramPipeline11, implementing ProgramPipelineImpl. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ + +#include "libANGLE/renderer/ProgramPipelineImpl.h" + +namespace rx +{ + +class ProgramPipeline11 : public ProgramPipelineImpl +{ + public: + ProgramPipeline11(const gl::ProgramPipelineState &state); + ~ProgramPipeline11() override; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp index 0a79b26df0..66b9476e7f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -7,146 +7,96 @@ // Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. #include "libANGLE/renderer/d3d/d3d11/Query11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "common/utilities.h" #include <GLES2/gl2ext.h> -#if defined(ANGLE_MINGW32_COMPAT) -typedef struct D3D11_QUERY_DATA_SO_STATISTICS { - UINT64 NumPrimitivesWritten; - UINT64 PrimitivesStorageNeeded; -} D3D11_QUERY_DATA_SO_STATISTICS; -#endif // ANGLE_MINGW32_COMPAT - -#ifndef ANGLE_D3D11_QDTD_AVAILABLE -typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT { - UINT64 Frequency; - BOOL Disjoint; -} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT; -#endif // MINGW32 +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -namespace rx +namespace { -Query11::Query11(Renderer11 *renderer, GLenum type) - : QueryImpl(type), - mResult(0), - mQueryFinished(false), - mRenderer(renderer), - mQuery(nullptr), - mTimestampBeginQuery(nullptr), - mTimestampEndQuery(nullptr) +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; -Query11::~Query11() -{ - SafeRelease(mQuery); - SafeRelease(mTimestampBeginQuery); - SafeRelease(mTimestampEndQuery); -} + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return currentResult + newResult; -gl::Error Query11::begin() -{ - if (mQuery == nullptr) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); - queryDesc.MiscFlags = 0; + case GL_TIME_ELAPSED_EXT: + return currentResult + newResult; - ID3D11Device *device = mRenderer->getDevice(); + case GL_TIMESTAMP_EXT: + return newResult; - HRESULT result = device->CreateQuery(&queryDesc, &mQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); - } + case GL_COMMANDS_COMPLETED_CHROMIUM: + return newResult; - // If we are doing time elapsed we also need a query to actually query the timestamp - if (getType() == GL_TIME_ELAPSED_EXT) - { - D3D11_QUERY_DESC desc; - desc.Query = D3D11_QUERY_TIMESTAMP; - desc.MiscFlags = 0; - result = device->CreateQuery(&desc, &mTimestampBeginQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", - result); - } - result = device->CreateQuery(&desc, &mTimestampEndQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", - result); - } - } + default: + UNREACHABLE(); + return 0; } +} - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); +} // anonymous namespace - context->Begin(mQuery); +namespace rx +{ - // If we are doing time elapsed query the begin timestamp - if (getType() == GL_TIME_ELAPSED_EXT) - { - context->End(mTimestampBeginQuery); - } - return gl::Error(GL_NO_ERROR); +Query11::QueryState::QueryState() : query(), beginTimestamp(), endTimestamp(), finished(false) +{ } -gl::Error Query11::end() +Query11::QueryState::~QueryState() { - ASSERT(mQuery); - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); +} - // If we are doing time elapsed query the end timestamp - if (getType() == GL_TIME_ELAPSED_EXT) - { - context->End(mTimestampEndQuery); - } +Query11::Query11(Renderer11 *renderer, GLenum type) + : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer) +{ + mActiveQuery = std::unique_ptr<QueryState>(new QueryState()); +} - context->End(mQuery); +Query11::~Query11() +{ + mRenderer->getStateManager()->onDeleteQueryObject(this); +} - mQueryFinished = false; - mResult = GL_FALSE; +gl::Error Query11::begin() +{ + mResultSum = 0; + mRenderer->getStateManager()->onBeginQuery(this); + return resume(); +} - return gl::Error(GL_NO_ERROR); +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); - mQueryFinished = true; - mResult = 0; - return gl::Error(GL_NO_ERROR); + mResultSum = 0; + mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState())); + return gl::NoError(); } template <typename T> gl::Error Query11::getResultBase(T *params) { - while (!mQueryFinished) - { - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - if (!mQueryFinished) - { - ScheduleYield(); - } - } + ASSERT(!mActiveQuery->query.valid()); + ANGLE_TRY(flush(true)); + ASSERT(mPendingQueries.empty()); + *params = static_cast<T>(mResultSum); - ASSERT(mQueryFinished); - *params = static_cast<T>(mResult); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query11::getResult(GLint *params) @@ -171,105 +121,197 @@ gl::Error Query11::getResult(GLuint64 *params) gl::Error Query11::isResultAvailable(bool *available) { - gl::Error error = testQuery(); - if (error.isError()) + ANGLE_TRY(flush(false)); + + *available = mPendingQueries.empty(); + return gl::NoError(); +} + +gl::Error Query11::pause() +{ + if (mActiveQuery->query.valid()) { - return error; + 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.get()); + } + + context->End(mActiveQuery->query.get()); + + mPendingQueries.push_back(std::move(mActiveQuery)); + mActiveQuery = std::unique_ptr<QueryState>(new QueryState()); } - *available = mQueryFinished; + return flush(false); +} + +gl::Error Query11::resume() +{ + if (!mActiveQuery->query.valid()) + { + ANGLE_TRY(flush(false)); + + GLenum queryType = getType(); + D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType); - return gl::Error(GL_NO_ERROR); + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = d3dQueryType; + queryDesc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateResource(queryDesc, &mActiveQuery->query)); + + // 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; + + ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->beginTimestamp)); + ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->endTimestamp)); + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + if (d3dQueryType != D3D11_QUERY_EVENT) + { + context->Begin(mActiveQuery->query.get()); + } + + // If we are doing time elapsed, query the begin timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + context->End(mActiveQuery->beginTimestamp.get()); + } + } + + return gl::NoError(); } -gl::Error Query11::testQuery() +gl::Error Query11::flush(bool force) { - if (!mQueryFinished) + while (!mPendingQueries.empty()) { - ASSERT(mQuery); + QueryState *query = mPendingQueries.front().get(); + do + { + ANGLE_TRY(testQuery(query)); + if (!query->finished && !force) + { + return gl::NoError(); + } + } 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: + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: { + ASSERT(queryState->query.valid()); UINT64 numPixels = 0; - HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0); + HRESULT result = + context->GetData(queryState->query.get(), &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); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { - mQueryFinished = true; - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + queryState->finished = true; + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; } } break; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: { - D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; - HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0); + ASSERT(queryState->query.valid()); + D3D11_QUERY_DATA_SO_STATISTICS soStats = {0}; + HRESULT result = + context->GetData(queryState->query.get(), &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); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { - mQueryFinished = true; - mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten); + queryState->finished = true; + mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten); } } break; case GL_TIME_ELAPSED_EXT: { + ASSERT(queryState->query.valid()); + ASSERT(queryState->beginTimestamp.valid()); + ASSERT(queryState->endTimestamp.valid()); D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0}; - HRESULT result = context->GetData(mQuery, &timeStats, sizeof(timeStats), 0); + HRESULT result = + context->GetData(queryState->query.get(), &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); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { UINT64 beginTime = 0; - HRESULT beginRes = - context->GetData(mTimestampBeginQuery, &beginTime, sizeof(UINT64), 0); + HRESULT beginRes = context->GetData(queryState->beginTimestamp.get(), + &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); + return gl::OutOfMemory() << "Failed to get the data of an internal query, " + << gl::FmtHR(beginRes); } UINT64 endTime = 0; - HRESULT endRes = - context->GetData(mTimestampEndQuery, &endTime, sizeof(UINT64), 0); + HRESULT endRes = context->GetData(queryState->endTimestamp.get(), &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); + return gl::OutOfMemory() << "Failed to get the data of an internal query, " + << gl::FmtHR(endRes); } if (beginRes == S_OK && endRes == S_OK) { - mQueryFinished = true; + queryState->finished = true; if (timeStats.Disjoint) { mRenderer->setGPUDisjoint(); } static_assert(sizeof(UINT64) == sizeof(unsigned long long), "D3D UINT64 isn't 64 bits"); - if (rx::IsUnsignedMultiplicationSafe(endTime - beginTime, 1000000000ull)) + + angle::CheckedNumeric<UINT64> checkedTime(endTime); + checkedTime -= beginTime; + checkedTime *= 1000000000ull; + checkedTime /= timeStats.Frequency; + if (checkedTime.IsValid()) { - mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency; + mResult = checkedTime.ValueOrDie(); } else { @@ -288,23 +330,46 @@ gl::Error Query11::testQuery() // 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 - mResult = 0; + ASSERT(!queryState->query.valid()); + mResult = 0; + queryState->finished = true; } break; - default: - UNREACHABLE(); + case GL_COMMANDS_COMPLETED_CHROMIUM: + { + ASSERT(queryState->query.valid()); + BOOL completed = 0; + HRESULT result = + context->GetData(queryState->query.get(), &completed, sizeof(completed), 0); + if (FAILED(result)) + { + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); + } + + if (result == S_OK) + { + queryState->finished = true; + ASSERT(completed == TRUE); + mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; + } + } break; + + default: + UNREACHABLE(); + break; } - if (!mQueryFinished && mRenderer->testDeviceLost()) + 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::OutOfMemory() << "Failed to test get query result, device is lost."; } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h index 29a6e6f85d..a88a8892aa 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h @@ -9,7 +9,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ +#include <deque> + #include "libANGLE/renderer/QueryImpl.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -19,31 +22,45 @@ class Query11 : public QueryImpl { public: Query11(Renderer11 *renderer, GLenum type); - virtual ~Query11(); + ~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; - 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); + gl::Error pause(); + gl::Error resume(); private: - gl::Error testQuery(); + struct QueryState final : private angle::NonCopyable + { + QueryState(); + ~QueryState(); + + d3d11::Query query; + d3d11::Query beginTimestamp; + d3d11::Query endTimestamp; + bool finished; + }; + + gl::Error flush(bool force); + gl::Error testQuery(QueryState *queryState); template <typename T> gl::Error getResultBase(T *params); GLuint64 mResult; - - bool mQueryFinished; + GLuint64 mResultSum; Renderer11 *mRenderer; - ID3D11Query *mQuery; - ID3D11Query *mTimestampBeginQuery; - ID3D11Query *mTimestampEndQuery; + + std::unique_ptr<QueryState> mActiveQuery; + std::deque<std::unique_ptr<QueryState>> mPendingQueries; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp index 2ee25cfb6c..5b85196c2e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -17,338 +17,180 @@ #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() + : mBlendStateCache(kMaxStates), + mRasterizerStateCache(kMaxStates), + mDepthStencilStateCache(kMaxStates), + mSamplerStateCache(kMaxStates) { } RenderStateCache::~RenderStateCache() { - clear(); -} - -void RenderStateCache::initialize(ID3D11Device *device) -{ - clear(); - mDevice = device; } void RenderStateCache::clear() { - ClearStateMap(mBlendStateCache); - ClearStateMap(mRasterizerStateCache); - ClearStateMap(mDepthStencilStateCache); - ClearStateMap(mSamplerStateCache); + mBlendStateCache.Clear(); + mRasterizerStateCache.Clear(); + mDepthStencilStateCache.Clear(); + mSamplerStateCache.Clear(); } -std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) +// static +d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState) { - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); - return hash; -} + d3d11::BlendStateKey key; + FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(context); + const UINT8 blendStateMask = + gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, + blendState.colorMaskBlue, blendState.colorMaskAlpha); -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]; + for (size_t i = 0; i < colorbuffers.size(); i++) + { + const gl::FramebufferAttachment *attachment = colorbuffers[i]; 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; + key.rtvMax = static_cast<uint32_t>(i) + 1; + key.rtvMasks[i] = + (gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask; } } - BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + return key; +} + +gl::Error RenderStateCache::getBlendState(Renderer11 *renderer, + const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState) +{ + auto keyIter = mBlendStateCache.Get(key); if (keyIter != mBlendStateCache.end()) { - BlendStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outBlendState = state.first; - return gl::Error(GL_NO_ERROR); + *outBlendState = &keyIter->second; + return gl::NoError(); } - 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; + TrimCache(kMaxStates, kGCLimit, "blend state", &mBlendStateCache); - 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); - } + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc; + D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0]; + const gl::BlendState &blendState = key.blendState; - 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); - } + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE; - mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + rtDesc0 = {}; - *outBlendState = dx11BlendState; - return gl::Error(GL_NO_ERROR); + if (blendState.blend) + { + rtDesc0.BlendEnable = true; + rtDesc0.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtDesc0.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtDesc0.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + rtDesc0.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtDesc0.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); } -} -std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) -{ - static const unsigned int seed = 0xABCDEF98; + rtDesc0.RenderTargetWriteMask = key.rtvMasks[0]; - std::size_t hash = 0; - MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); - return hash; -} + for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + blendDesc.RenderTarget[i] = rtDesc0; + blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i]; + } -bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) -{ - return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; + d3d11::BlendState d3dBlendState; + ANGLE_TRY(renderer->allocateResource(blendDesc, &d3dBlendState)); + const auto &iter = mBlendStateCache.Put(key, std::move(d3dBlendState)); + + *outBlendState = &iter->second; + + return gl::NoError(); } -gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, +gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer, + 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 = {}; + d3d11::RasterizerStateKey key; key.rasterizerState = rasterState; - key.scissorEnabled = scissorEnabled; + key.scissorEnabled = scissorEnabled ? 1 : 0; - RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + auto keyIter = mRasterizerStateCache.Get(key); if (keyIter != mRasterizerStateCache.end()) { - RasterizerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outRasterizerState = state.first; - return gl::Error(GL_NO_ERROR); + *outRasterizerState = keyIter->second.get(); + return gl::NoError(); } - 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); + TrimCache(kMaxStates, kGCLimit, "rasterizer state", &mRasterizerStateCache); - // Disable culling if drawing points - if (rasterState.pointDrawMode) - { - cullMode = D3D11_CULL_NONE; - } + D3D11_CULL_MODE cullMode = + gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); - 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) + // Disable culling if drawing points + if (rasterState.pointDrawMode) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + cullMode = D3D11_CULL_NONE; } - gl::DepthStencilState glState = originalState; - if (disableDepth) + 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) { - glState.depthTest = false; - glState.depthMask = false; + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; } - - if (disableStencil) + else { - glState.stencilWritemask = 0; - glState.stencilBackWritemask = 0; - glState.stencilTest = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; } - auto keyIter = mDepthStencilStateCache.find(glState); + d3d11::RasterizerState dx11RasterizerState; + ANGLE_TRY(renderer->allocateResource(rasterDesc, &dx11RasterizerState)); + *outRasterizerState = dx11RasterizerState.get(); + mRasterizerStateCache.Put(key, std::move(dx11RasterizerState)); + + return gl::NoError(); +} + +gl::Error RenderStateCache::getDepthStencilState(Renderer11 *renderer, + const gl::DepthStencilState &glState, + const d3d11::DepthStencilState **outDSState) +{ + auto keyIter = mDepthStencilStateCache.Get(glState); if (keyIter != mDepthStencilStateCache.end()) { - DepthStencilStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outDSState = state.first; - return gl::Error(GL_NO_ERROR); + *outDSState = &keyIter->second; + return gl::NoError(); } - 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); - } + TrimCache(kMaxStates, kGCLimit, "depth stencil state", &mDepthStencilStateCache); D3D11_DEPTH_STENCIL_DESC dsDesc = {0}; dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE; @@ -366,107 +208,66 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or 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); - } + d3d11::DepthStencilState dx11DepthStencilState; + ANGLE_TRY(renderer->allocateResource(dsDesc, &dx11DepthStencilState)); + const auto &iter = mDepthStencilStateCache.Put(glState, std::move(dx11DepthStencilState)); - mDepthStencilStateCache.insert( - std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++))); + *outDSState = &iter->second; - *outDSState = dx11DepthStencilState; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +gl::Error RenderStateCache::getSamplerState(Renderer11 *renderer, + const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState) { - 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) + auto keyIter = mSamplerStateCache.Get(samplerState); + if (keyIter != mSamplerStateCache.end()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + *outSamplerState = keyIter->second.get(); + return gl::NoError(); } - SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); - if (keyIter != mSamplerStateCache.end()) + TrimCache(kMaxStates, kGCLimit, "sampler state", &mSamplerStateCache); + + const auto &featureLevel = renderer->getRenderer11DeviceCaps().featureLevel; + + 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, featureLevel); + 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 (featureLevel <= D3D_FEATURE_LEVEL_9_3) { - SamplerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outSamplerState = state.first; - return gl::Error(GL_NO_ERROR); + // 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; } - 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 = static_cast<UINT>(samplerState.maxAnisotropy); - 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; - } + d3d11::SamplerState dx11SamplerState; + ANGLE_TRY(renderer->allocateResource(samplerDesc, &dx11SamplerState)); + *outSamplerState = dx11SamplerState.get(); + mSamplerStateCache.Put(samplerState, std::move(dx11SamplerState)); - 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); - } + return gl::NoError(); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h index 82cb13903c..7501e83fc4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -10,9 +10,11 @@ #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 "libANGLE/Error.h" +#include "libANGLE/SizedMRUCache.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include <unordered_map> @@ -21,6 +23,42 @@ namespace gl class Framebuffer; } +namespace std +{ +template <> +struct hash<rx::d3d11::BlendStateKey> +{ + size_t operator()(const rx::d3d11::BlendStateKey &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash<rx::d3d11::RasterizerStateKey> +{ + size_t operator()(const rx::d3d11::RasterizerStateKey &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash<gl::DepthStencilState> +{ + size_t operator()(const gl::DepthStencilState &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash<gl::SamplerState> +{ + size_t operator()(const gl::SamplerState &key) const { return angle::ComputeGenericHash(key); } +}; +} // namespace std + namespace rx { class Renderer11; @@ -28,87 +66,58 @@ class Renderer11; class RenderStateCache : angle::NonCopyable { public: - RenderStateCache(Renderer11 *renderer); + RenderStateCache(); 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); + static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState); + gl::Error getBlendState(Renderer11 *renderer, + const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState); + gl::Error getRasterizerState(Renderer11 *renderer, + const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(Renderer11 *renderer, + const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState); + gl::Error getSamplerState(Renderer11 *renderer, + const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState); private: - Renderer11 *mRenderer; - unsigned long long mCounter; + // 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 + // TODO(ShahmeerEsmail): Revisit the cache sizes to make sure they are appropriate for most + // scenarios. + static constexpr unsigned int kMaxStates = 4096; + + // The cache tries to clean up this many states at once. + static constexpr unsigned int kGCLimit = 128; // 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; + using BlendStateMap = angle::base::HashingMRUCache<d3d11::BlendStateKey, d3d11::BlendState>; 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; + using RasterizerStateMap = + angle::base::HashingMRUCache<d3d11::RasterizerStateKey, d3d11::RasterizerState>; 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; + using DepthStencilStateMap = + angle::base::HashingMRUCache<gl::DepthStencilState, d3d11::DepthStencilState>; 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; + using SamplerStateMap = angle::base::HashingMRUCache<gl::SamplerState, d3d11::SamplerState>; SamplerStateMap mSamplerStateCache; - - ID3D11Device *mDevice; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp index cdfcacc287..594a382a72 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -18,7 +18,9 @@ namespace rx { -static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +namespace +{ +bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) { ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource); if (texture1D) @@ -62,7 +64,7 @@ static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLeve return false; } -static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) +unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; view->GetDesc(&rtvDesc); @@ -72,58 +74,58 @@ static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11Rende 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; + 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); + GetTextureProperties(resource, &mipLevels, &samples); return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) +unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; view->GetDesc(&dsvDesc); @@ -133,157 +135,170 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth 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; + 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); + GetTextureProperties(resource, &mipLevels, &samples); return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), +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() +{ + ASSERT(mBroadcastChannel.empty()); +} + +void RenderTarget11::signalDirty(const gl::Context *context) +{ + mBroadcastChannel.signal(context); + + // Clear the list. We can't do this in the receiver because it would mutate during iteration. + mBroadcastChannel.reset(); +} + +TextureRenderTarget11::TextureRenderTarget11(d3d11::RenderTargetView &&rtv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + const d3d11::SharedSRV &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), - mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), - mRenderTarget(rtv), - mDepthStencil(NULL), - mShaderResource(srv) + mRenderTarget(std::move(rtv)), + mDepthStencil(), + mShaderResource(srv.makeCopy()), + mBlitShaderResource(blitSRV.makeCopy()) { - if (mTexture) - { - mTexture->AddRef(); - } - - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mRenderTarget && mTexture) + if (mRenderTarget.valid() && mTexture.valid()) { - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - mDXGIFormat = desc.Format; + mSubresourceIndex = GetRTVSubresourceIndex(mTexture.get(), mRenderTarget.get()); } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); } -TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), +TextureRenderTarget11::TextureRenderTarget11(d3d11::DepthStencilView &&dsv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &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), - mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), - mRenderTarget(NULL), - mDepthStencil(dsv), - mShaderResource(srv) + mRenderTarget(), + mDepthStencil(std::move(dsv)), + mShaderResource(srv.makeCopy()), + mBlitShaderResource() { - if (mTexture) + if (mDepthStencil.valid() && mTexture.valid()) { - mTexture->AddRef(); - } - - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mDepthStencil && mTexture) - { - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - mDXGIFormat = desc.Format; + mSubresourceIndex = GetDSVSubresourceIndex(mTexture.get(), mDepthStencil.get()); } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); } TextureRenderTarget11::~TextureRenderTarget11() { - SafeRelease(mTexture); - SafeRelease(mRenderTarget); - SafeRelease(mDepthStencil); - SafeRelease(mShaderResource); } -ID3D11Resource *TextureRenderTarget11::getTexture() const +const TextureHelper11 &TextureRenderTarget11::getTexture() const { return mTexture; } -ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const +const d3d11::RenderTargetView &TextureRenderTarget11::getRenderTargetView() const { return mRenderTarget; } -ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const +const d3d11::DepthStencilView &TextureRenderTarget11::getDepthStencilView() const { return mDepthStencil; } -ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const +const d3d11::SharedSRV &TextureRenderTarget11::getShaderResourceView() const { return mShaderResource; } +const d3d11::SharedSRV &TextureRenderTarget11::getBlitShaderResourceView() const +{ + return mBlitShaderResource; +} + GLsizei TextureRenderTarget11::getWidth() const { return mWidth; @@ -314,14 +329,11 @@ unsigned int TextureRenderTarget11::getSubresourceIndex() const return mSubresourceIndex; } -DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const -{ - return mDXGIFormat; -} - -SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth) - : mSwapChain(swapChain), - mRenderer(renderer), +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, + Renderer11 *renderer, + bool depth) + : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)), + mSwapChain(swapChain), mDepth(depth) { ASSERT(mSwapChain); @@ -348,43 +360,46 @@ GLsizei SurfaceRenderTarget11::getDepth() const GLenum SurfaceRenderTarget11::getInternalFormat() const { - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); + return GetSurfaceRTFormat(mDepth, mSwapChain); } GLsizei SurfaceRenderTarget11::getSamples() const { - // Our EGL surfaces do not support multisampling. - return 0; + return mSwapChain->getSamples(); } -ID3D11Resource *SurfaceRenderTarget11::getTexture() const +const TextureHelper11 &SurfaceRenderTarget11::getTexture() const { return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); } -ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const +const d3d11::RenderTargetView &SurfaceRenderTarget11::getRenderTargetView() const { - return (mDepth ? NULL : mSwapChain->getRenderTarget()); + ASSERT(!mDepth); + return mSwapChain->getRenderTarget(); } -ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const +const d3d11::DepthStencilView &SurfaceRenderTarget11::getDepthStencilView() const { - return (mDepth ? mSwapChain->getDepthStencil() : NULL); + ASSERT(mDepth); + return mSwapChain->getDepthStencil(); } -ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const +const d3d11::SharedSRV &SurfaceRenderTarget11::getShaderResourceView() const { - return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource()); + return (mDepth ? mSwapChain->getDepthStencilShaderResource() + : mSwapChain->getRenderTargetShaderResource()); } -unsigned int SurfaceRenderTarget11::getSubresourceIndex() const +const d3d11::SharedSRV &SurfaceRenderTarget11::getBlitShaderResourceView() const { - return 0; + // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits. + return getShaderResourceView(); } -DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const +unsigned int SurfaceRenderTarget11::getSubresourceIndex() const { - return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getRenderer11DeviceCaps()).texFormat; + return 0; } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h index d47b237c09..db49cac9f5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h @@ -11,6 +11,9 @@ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" namespace rx { @@ -20,28 +23,51 @@ class Renderer11; class RenderTarget11 : public RenderTargetD3D { public: - RenderTarget11() { } - virtual ~RenderTarget11() { } + RenderTarget11(const d3d11::Format &formatSet); + ~RenderTarget11() override; - virtual ID3D11Resource *getTexture() const = 0; - virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; - virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; - virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; + virtual const TextureHelper11 &getTexture() const = 0; + virtual const d3d11::RenderTargetView &getRenderTargetView() const = 0; + virtual const d3d11::DepthStencilView &getDepthStencilView() const = 0; + virtual const d3d11::SharedSRV &getShaderResourceView() const = 0; + virtual const d3d11::SharedSRV &getBlitShaderResourceView() const = 0; virtual unsigned int getSubresourceIndex() const = 0; - virtual DXGI_FORMAT getDXGIFormat() const = 0; + void signalDirty(const gl::Context *context) override; + OnRenderTargetDirtyChannel *getBroadcastChannel() { return &mBroadcastChannel; } + + const d3d11::Format &getFormatSet() const { return mFormatSet; } + + protected: + OnRenderTargetDirtyChannel 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, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - virtual ~TextureRenderTarget11(); + TextureRenderTarget11(d3d11::RenderTargetView &&rtv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + const d3d11::SharedSRV &blitSRV, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + TextureRenderTarget11(d3d11::DepthStencilView &&dsv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + ~TextureRenderTarget11() override; GLsizei getWidth() const override; GLsizei getHeight() const override; @@ -49,35 +75,37 @@ class TextureRenderTarget11 : public RenderTarget11 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; + const TextureHelper11 &getTexture() const override; + const d3d11::RenderTargetView &getRenderTargetView() const override; + const d3d11::DepthStencilView &getDepthStencilView() const override; + const d3d11::SharedSRV &getShaderResourceView() const override; + const d3d11::SharedSRV &getBlitShaderResourceView() const override; unsigned int getSubresourceIndex() const override; - DXGI_FORMAT getDXGIFormat() const override; - private: GLsizei mWidth; GLsizei mHeight; GLsizei mDepth; GLenum mInternalFormat; - DXGI_FORMAT mDXGIFormat; GLsizei mSamples; unsigned int mSubresourceIndex; - ID3D11Resource *mTexture; - ID3D11RenderTargetView *mRenderTarget; - ID3D11DepthStencilView *mDepthStencil; - ID3D11ShaderResourceView *mShaderResource; + TextureHelper11 mTexture; + d3d11::RenderTargetView mRenderTarget; + d3d11::DepthStencilView mDepthStencil; + d3d11::SharedSRV mShaderResource; + + // Shader resource view to use with internal blit shaders. Not set for depth/stencil render + // targets. + d3d11::SharedSRV mBlitShaderResource; }; class SurfaceRenderTarget11 : public RenderTarget11 { public: SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth); - virtual ~SurfaceRenderTarget11(); + ~SurfaceRenderTarget11() override; GLsizei getWidth() const override; GLsizei getHeight() const override; @@ -85,21 +113,19 @@ class SurfaceRenderTarget11 : public RenderTarget11 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; + const TextureHelper11 &getTexture() const override; + const d3d11::RenderTargetView &getRenderTargetView() const override; + const d3d11::DepthStencilView &getDepthStencilView() const override; + const d3d11::SharedSRV &getShaderResourceView() const override; + const d3d11::SharedSRV &getBlitShaderResourceView() const override; unsigned int getSubresourceIndex() const override; - DXGI_FORMAT getDXGIFormat() const override; - private: SwapChain11 *mSwapChain; - Renderer11 *mRenderer; bool mDepth; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 5118bdbe9c..b0ef9abddc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -9,56 +9,64 @@ #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include <EGL/eglext.h> +#include <versionhelpers.h> #include <sstream> -#if !defined(ANGLE_MINGW32_COMPAT) && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP -#include <VersionHelpers.h> -#endif #include "common/tls.h" #include "common/utilities.h" #include "libANGLE/Buffer.h" +#include "libANGLE/Context.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/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/histogram_macros.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.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/renderer/d3d/d3d11/Blit11.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Clear11.h" -#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/Context11.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/TransformFeedbackD3D.h" -#include "libANGLE/renderer/d3d/VertexDataManager.h" -#include "libANGLE/State.h" -#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/renderer_utils.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. @@ -72,12 +80,6 @@ #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 { @@ -89,25 +91,6 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -#if defined(ANGLE_ENABLE_D3D11_1) -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 -} -#endif - enum ANGLEFeatureLevel { ANGLE_FEATURE_LEVEL_INVALID, @@ -123,14 +106,18 @@ 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; + 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; + case D3D_FEATURE_LEVEL_11_1: + return ANGLE_FEATURE_LEVEL_11_1; + default: + return ANGLE_FEATURE_LEVEL_INVALID; } } @@ -144,7 +131,7 @@ void SetLineLoopIndices(GLuint *dest, size_t count) } template <typename T> -void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count) +void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count) { const T *srcPtr = static_cast<const T *>(indices); for (size_t i = 0; i < count; ++i) @@ -165,7 +152,7 @@ void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) } template <typename T> -void CopyLineLoopIndicesWithRestart(const GLvoid *indices, +void CopyLineLoopIndicesWithRestart(const void *indices, size_t count, GLenum indexType, std::vector<GLuint> *bufferOut) @@ -206,7 +193,7 @@ void CopyLineLoopIndicesWithRestart(const GLvoid *indices, } } -void GetLineLoopIndices(const GLvoid *indices, +void GetLineLoopIndices(const void *indices, GLenum indexType, GLuint count, bool usePrimitiveRestartFixedIndex, @@ -257,7 +244,7 @@ void GetLineLoopIndices(const GLvoid *indices, } template <typename T> -void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris) +void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris) { const T *srcPtr = static_cast<const T *>(indices); @@ -270,7 +257,7 @@ void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTr } template <typename T> -void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, +void CopyTriangleFanIndicesWithRestart(const void *indices, GLuint indexCount, GLenum indexType, std::vector<GLuint> *bufferOut) @@ -314,7 +301,7 @@ void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, } } -void GetTriFanIndices(const GLvoid *indices, +void GetTriFanIndices(const void *indices, GLenum indexType, GLuint count, bool usePrimitiveRestartFixedIndex, @@ -365,60 +352,135 @@ void GetTriFanIndices(const GLvoid *indices, } } +bool DrawCallNeedsTranslation(const gl::Context *context, GLenum mode) +{ + const auto &glState = context->getGLState(); + const gl::VertexArray *vertexArray = glState.getVertexArray(); + VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray); + // Direct drawing doesn't support dynamic attribute storage since it needs the first and count + // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported + // either since we need to simulate them in D3D. + if (vertexArray11->hasActiveDynamicAttrib(context) || mode == GL_LINE_LOOP || + mode == GL_TRIANGLE_FAN) + { + return true; + } + + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + if (InstancedPointSpritesActive(programD3D, mode)) + { + return true; + } + + return false; +} + +bool IsArrayRTV(ID3D11RenderTargetView *rtv) +{ + D3D11_RENDER_TARGET_VIEW_DESC desc; + rtv->GetDesc(&desc); + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY && + desc.Texture1DArray.ArraySize > 1) + return true; + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY && + desc.Texture2DArray.ArraySize > 1) + return true; + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY && + desc.Texture2DMSArray.ArraySize > 1) + return true; + return false; +} + +int GetAdjustedInstanceCount(const gl::Program *program, int instanceCount) +{ + if (!program->usesMultiview()) + { + return instanceCount; + } + if (instanceCount == 0) + { + return program->getNumViews(); + } + return program->getNumViews() * instanceCount; +} + +const uint32_t ScratchMemoryBufferLifetime = 1000; + +void PopulateFormatDeviceCaps(ID3D11Device *device, + DXGI_FORMAT format, + UINT *outSupport, + UINT *outMaxSamples) +{ + if (FAILED(device->CheckFormatSupport(format, outSupport))) + { + *outSupport = 0; + } + + *outMaxSamples = 0; + for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2) + { + UINT qualityCount = 0; + if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) || + qualityCount == 0) + { + break; + } + + *outMaxSamples = sampleCount; + } +} + +bool CullsEverything(const gl::State &glState) +{ + return (glState.getRasterizerState().cullFace && + glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack); +} + } // anonymous namespace +Renderer11DeviceCaps::Renderer11DeviceCaps() = default; + Renderer11::Renderer11(egl::Display *display) : RendererD3D(display), - mStateCache(this), + mCreateDebugDevice(false), + mStateCache(), mStateManager(this), - mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()) -#if !defined(ANGLE_MINGW32_COMPAT) - ,mDebug(nullptr) -#endif + mLastHistogramUpdateTime( + ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())), + mDebug(nullptr), + mScratchMemoryBuffer(ScratchMemoryBufferLifetime), + mAnnotator(nullptr) { - mVertexDataManager = NULL; - mIndexDataManager = NULL; + mLineLoopIB = nullptr; + mTriangleFanIB = nullptr; - mLineLoopIB = NULL; - mTriangleFanIB = NULL; - mAppliedIBChanged = false; + mBlit = nullptr; + mPixelTransfer = nullptr; - mBlit = NULL; - mPixelTransfer = NULL; + mClear = nullptr; - mClear = NULL; + mTrim = nullptr; - mTrim = NULL; - - mSyncQuery = NULL; - - mRenderer11DeviceCaps.supportsClearView = false; + 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; + mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false; + mRenderer11DeviceCaps.supportsDXGI1_2 = false; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G5R5A1support = 0; + + mD3d11Module = nullptr; + mDxgiModule = nullptr; + mDCompModule = nullptr; mCreatedWithDeviceEXT = false; mEGLDevice = nullptr; - mDevice = NULL; - mDeviceContext = NULL; - mDeviceContext1 = NULL; - mDxgiAdapter = NULL; - mDxgiFactory = NULL; - - mDriverConstantBufferVS = NULL; - mDriverConstantBufferPS = NULL; - - mAppliedVertexShader = NULL; - mAppliedGeometryShader = NULL; - mAppliedPixelShader = NULL; - - mAppliedNumXFBBindings = static_cast<size_t>(-1); + mDevice = nullptr; + mDeviceContext = nullptr; + mDeviceContext1 = nullptr; + mDeviceContext3 = nullptr; + mDxgiAdapter = nullptr; + mDxgiFactory = nullptr; ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); @@ -426,13 +488,21 @@ Renderer11::Renderer11(egl::Display *display) { const auto &attributes = mDisplay->getAttributeMap(); - EGLint requestedMajorVersion = - attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); - EGLint requestedMinorVersion = - attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + 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 >= 1) + { + // This could potentially lead to failed context creation if done on a system + // without the platform update which installs DXGI 1.2. Currently, for Chrome users + // D3D11 contexts are only created if the platform update is available, so this + // should not cause any issues. + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1); + } if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) { mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); @@ -451,11 +521,7 @@ Renderer11::Renderer11(egl::Display *display) } } -#if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) -#else if (requestedMajorVersion == 9 && requestedMinorVersion == 3) -#endif { if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) { @@ -473,8 +539,8 @@ Renderer11::Renderer11(egl::Display *display) #endif } - EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + 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: @@ -497,9 +563,11 @@ Renderer11::Renderer11(egl::Display *display) UNREACHABLE(); } - const EGLenum presentPath = attributes.get(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, - EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE); + 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); + + mCreateDebugDevice = ShouldUseDebugLayers(attributes); } else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) { @@ -509,11 +577,22 @@ Renderer11::Renderer11(egl::Display *display) // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE // mAvailableFeatureLevels defaults to empty - mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; + mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; mPresentPathFastEnabled = false; } - initializeDebugAnnotator(); +// 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() @@ -529,20 +608,17 @@ egl::Error Renderer11::initialize() { HRESULT result = S_OK; - egl::Error error = initializeD3DDevice(); - if (error.isError()) - { - return error; - } + 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. + // 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()); + HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); if (hwnd) { DWORD currentProcessId = GetCurrentProcessId(); @@ -557,13 +633,12 @@ egl::Error Renderer11::initialize() if (requireDXGI1_2) { - IDXGIDevice2 *dxgiDevice2 = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + IDXGIDevice2 *dxgiDevice2 = nullptr; + 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."); + return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI) + << "DXGI 1.2 required to present to HWNDs owned by another process."; } SafeRelease(dxgiDevice2); } @@ -573,90 +648,83 @@ egl::Error Renderer11::initialize() { TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); - // Cast the DeviceContext to a DeviceContext1. + // Cast the DeviceContext to a DeviceContext1 and DeviceContext3. // This could fail on Windows 7 without the Platform Update. - // Don't error in this case- just don't use mDeviceContext1. -#if defined(ANGLE_ENABLE_D3D11_1) + // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3. mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext); -#endif + mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext); - IDXGIDevice *dxgiDevice = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + IDXGIDevice *dxgiDevice = nullptr; + 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."); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device."; } - result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + 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"); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not retrieve DXGI adapter"; } SafeRelease(dxgiDevice); -#if defined(ANGLE_ENABLE_D3D11_1) 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) + // 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 != nullptr) { DXGI_ADAPTER_DESC2 adapterDesc2 = {}; - result = dxgiAdapter2->GetDesc2(&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; + // 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; + mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; + mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; } } else -#endif { result = mDxgiAdapter->GetDesc(&mAdapterDescription); } -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(dxgiAdapter2); -#endif if (FAILED(result)) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not read DXGI adaptor description."); + return egl::EglNotInitialized(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); + 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."); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not create DXGI factory."; } } -#if !defined(ANGLE_MINGW32_COMPAT) // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + if (mCreateDebugDevice) { TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)"); ID3D11InfoQueue *infoQueue; @@ -664,29 +732,33 @@ egl::Error Renderer11::initialize() if (SUCCEEDED(result)) { - D3D11_MESSAGE_ID hideMessages[] = - { - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; + 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; + filter.DenyList.pIDList = hideMessages; infoQueue->AddStorageFilterEntries(&filter); SafeRelease(infoQueue); } } -#endif #if !defined(NDEBUG) mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice); #endif -#endif // !ANGLE_MINGW32_COMPAT - initializeDevice(); + ANGLE_TRY(initializeDevice()); + + return egl::NoError(); +} - return egl::Error(EGL_SUCCESS); +HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug) +{ + return createDevice( + nullptr, mRequestedDriverType, nullptr, debug ? D3D11_CREATE_DEVICE_DEBUG : 0, + mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); } egl::Error Renderer11::initializeD3DDevice() @@ -706,8 +778,8 @@ egl::Error Renderer11::initializeD3DDevice() if (mD3d11Module == nullptr || mDxgiModule == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, - "Could not load D3D11 or DXGI library."); + return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) + << "Could not load D3D11 or DXGI library."; } // create the D3D11 device @@ -717,68 +789,76 @@ egl::Error Renderer11::initializeD3DDevice() if (D3D11CreateDevice == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, - "Could not retrieve D3D11CreateDevice address."); + return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) + << "Could not retrieve D3D11CreateDevice address."; } } #endif -#ifdef _DEBUG + if (mCreateDebugDevice) { 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); - } + result = callD3D11CreateDevice(D3D11CreateDevice, true); - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && + mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + { + // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. + // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature + // levels to fall back on. + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + result = callD3D11CreateDevice(D3D11CreateDevice, true); + } + + if (!mDevice || FAILED(result)) + { + WARN() << "Failed creating Debug D3D11 device - falling back to release runtime."; + } } 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); + result = callD3D11CreateDevice(D3D11CreateDevice, false); + + if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && + mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + { + // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. + // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature + // levels to fall back on. + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + result = callD3D11CreateDevice(D3D11CreateDevice, false); + } // 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."); + return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR) + << "Could not create D3D11 device."; } } } else { // We should use the inputted D3D11 device instead - void *device = nullptr; - egl::Error error = mEGLDevice->getDevice(&device); - if (error.isError()) - { - return error; - } + 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."); + return egl::EglNotInitialized() << "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."); + return egl::EglNotInitialized() + << "Inputted D3D11 device must be Feature Level 9_3 or greater."; } // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. @@ -788,27 +868,24 @@ egl::Error Renderer11::initializeD3DDevice() mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); } + mResourceManager11.setAllocationsInitialized(mCreateDebugDevice); + d3d11::SetDebugName(mDeviceContext, "DeviceContext"); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } // 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() +egl::Error 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()); + mStateCache.clear(); ASSERT(!mBlit); mBlit = new Blit11(this); @@ -820,7 +897,8 @@ void Renderer11::initializeDevice() // 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 = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE); + EGLint enableAutoTrim = static_cast<EGLint>( + attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE)); if (enableAutoTrim == EGL_TRUE) { @@ -831,19 +909,12 @@ void Renderer11::initializeDevice() ASSERT(!mPixelTransfer); mPixelTransfer = new PixelTransfer11(this); - const gl::Caps &rendererCaps = getRendererCaps(); - - mStateManager.initialize(rendererCaps); - - mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - - mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - - mStateManager.initialize(rendererCaps); + const gl::Caps &rendererCaps = getNativeCaps(); - markAllStateDirty(); + if (mStateManager.initialize(rendererCaps, getNativeExtensions()).isError()) + { + return egl::EglBadAlloc() << "Error initializing state manager."; + } // Gather stats on DXGI and D3D feature level ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); @@ -859,57 +930,117 @@ void Renderer11::initializeDevice() angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1; } - ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", - angleFeatureLevel, + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel, NUM_ANGLE_FEATURE_LEVELS); - // TODO(jmadill): use context caps, and place in common D3D location - mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes); + return egl::NoError(); } void Renderer11::populateRenderer11DeviceCaps() { HRESULT hr = S_OK; -#if defined(ANGLE_ENABLE_D3D11_1) + 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)); + 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); + mRenderer11DeviceCaps.supportsConstantBufferOffsets = + (d3d11Options.ConstantBufferOffsetting != FALSE); } } -#endif - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, &(mRenderer11DeviceCaps.B5G6R5support)); - if (FAILED(hr)) + if (mDeviceContext3) { - mRenderer11DeviceCaps.B5G6R5support = 0; + D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3; + HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3, + sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3)); + if (SUCCEEDED(result)) + { + mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = + (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE); + } } - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM, &(mRenderer11DeviceCaps.B4G4R4A4support)); - if (FAILED(hr)) + mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs = + mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0; + + if (getWorkarounds().disableB5G6R5Support) { - mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B5G6R5maxSamples = 0; } - - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM, &(mRenderer11DeviceCaps.B5G5R5A1support)); - if (FAILED(hr)) + else { - mRenderer11DeviceCaps.B5G5R5A1support = 0; + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM, + &mRenderer11DeviceCaps.B5G6R5support, + &mRenderer11DeviceCaps.B5G6R5maxSamples); } -#if defined(ANGLE_ENABLE_D3D11_1) + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM, + &mRenderer11DeviceCaps.B4G4R4A4support, + &mRenderer11DeviceCaps.B4G4R4A4maxSamples); + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM, + &mRenderer11DeviceCaps.B5G5R5A1support, + &mRenderer11DeviceCaps.B5G5R5A1maxSamples); + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter); mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); SafeRelease(dxgiAdapter2); +} + +gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig( + const gl::TextureCaps &colorBufferFormatCaps, + const gl::TextureCaps &depthStencilBufferFormatCaps) const +{ + gl::SupportedSampleSet sampleCounts; + +#if 0 // Disabling support for multisampling with Qt5 as it's causing a crash in the D3D11 shaders. + + // Generate a new set from the set intersection of sample counts between the color and depth + // format caps. + std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(), + colorBufferFormatCaps.sampleCounts.end(), + depthStencilBufferFormatCaps.sampleCounts.begin(), + depthStencilBufferFormatCaps.sampleCounts.end(), + std::inserter(sampleCounts, sampleCounts.begin())); + + // Format of GL_NONE results in no supported sample counts. + // Add back the color sample counts to the supported sample set. + if (depthStencilBufferFormatCaps.sampleCounts.empty()) + { + sampleCounts = colorBufferFormatCaps.sampleCounts; + } + else if (colorBufferFormatCaps.sampleCounts.empty()) + { + // Likewise, add back the depth sample counts to the supported sample set. + sampleCounts = depthStencilBufferFormatCaps.sampleCounts; + } + #endif + + // Always support 0 samples + sampleCounts.insert(0); + + return sampleCounts; } -egl::ConfigSet Renderer11::generateConfigs() const +egl::ConfigSet Renderer11::generateConfigs() { std::vector<GLenum> colorBufferFormats; @@ -920,6 +1051,14 @@ egl::ConfigSet Renderer11::generateConfigs() const // 24-bit supported formats colorBufferFormats.push_back(GL_RGB8_OES); + if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + { + // Additional high bit depth formats added in D3D 10.0 + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx + colorBufferFormats.push_back(GL_RGBA16F); + colorBufferFormats.push_back(GL_RGB10_A2); + } + if (!mPresentPathFastEnabled) { // 16-bit supported formats @@ -930,15 +1069,13 @@ egl::ConfigSet Renderer11::generateConfigs() const colorBufferFormats.push_back(GL_RGB565); } - static const GLenum depthStencilBufferFormats[] = - { - GL_NONE, - GL_DEPTH24_STENCIL8_OES, - GL_DEPTH_COMPONENT16, + static const GLenum depthStencilBufferFormats[] = { + GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, + GL_STENCIL_INDEX8, }; - const gl::Caps &rendererCaps = getRendererCaps(); - const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + const gl::Caps &rendererCaps = getNativeCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); const EGLint optimalSurfaceOrientation = mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; @@ -946,7 +1083,8 @@ egl::ConfigSet Renderer11::generateConfigs() const egl::ConfigSet configs; for (GLenum colorBufferInternalFormat : colorBufferFormats) { - const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + const gl::TextureCaps &colorBufferFormatCaps = + rendererTextureCaps.get(colorBufferInternalFormat); if (!colorBufferFormatCaps.renderable) { continue; @@ -963,64 +1101,87 @@ egl::ConfigSet Renderer11::generateConfigs() const } const gl::InternalFormat &colorBufferFormatInfo = - gl::GetInternalFormatInfo(colorBufferInternalFormat); + gl::GetSizedInternalFormatInfo(colorBufferInternalFormat); const gl::InternalFormat &depthStencilBufferFormatInfo = - gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); - - 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.configID = static_cast<EGLint>(configs.size() + 1); - // Can only support a conformant ES2 with feature level greater than 10.0. - config.conformant = (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) - ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) - : 0; - config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; - - // PresentPathFast may not be conformant - if (mPresentPathFastEnabled) + gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat); + const gl::Version &maxVersion = getMaxSupportedESVersion(); + + const gl::SupportedSampleSet sampleCounts = + generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps); + + for (GLuint sampleCount : sampleCounts) { + 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) && (sampleCount <= 1)); + config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) || + (colorBufferFormatInfo.format == GL_BGRA_EXT)) && + (sampleCount <= 1)); + 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.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.0 - config.renderableType = - EGL_OPENGL_ES2_BIT | ((mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) - ? EGL_OPENGL_ES3_BIT_KHR - : 0); - 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); + config.sampleBuffers = (sampleCount == 0) ? 0 : 1; + config.samples = sampleCount; + 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; + config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType( + colorBufferFormatInfo.componentType); + + configs.add(config); + } } } @@ -1037,8 +1198,9 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions outExtensions->d3dShareHandleClientBuffer = true; outExtensions->surfaceD3DTexture2DShareHandle = true; } + outExtensions->d3dTextureClientBuffer = true; - outExtensions->keyedMutex = true; + outExtensions->keyedMutex = true; outExtensions->querySurfacePointer = true; outExtensions->windowFixedSize = true; @@ -1048,624 +1210,350 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions // D3D11 does not support present with dirty rectangles until DXGI 1.2. outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; - outExtensions->createContext = true; - outExtensions->deviceQuery = true; - outExtensions->createContextNoError = 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; + + // Contexts are virtualized so textures can be shared globally + outExtensions->displayTextureShareGroup = true; + + // getSyncValues requires direct composition. + outExtensions->getSyncValues = outExtensions->directComposition; + + // D3D11 can be used without a swap chain + outExtensions->surfacelessContext = true; + + // All D3D feature levels support robust resource init + outExtensions->robustResourceInitialization = true; } gl::Error Renderer11::flush() { mDeviceContext->Flush(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::finish() { - HRESULT result; - - if (!mSyncQuery) + if (!mSyncQuery.valid()) { D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; + 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); - } + ANGLE_TRY(allocateResource(queryDesc, &mSyncQuery)); } - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); + mDeviceContext->End(mSyncQuery.get()); + HRESULT result = S_OK; + unsigned int attempt = 0; do { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + unsigned int flushFrequency = 100; + UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH; + attempt++; + + result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result); } - // Keep polling, but allow other threads to do something useful first - ScheduleYield(); + if (result == S_FALSE) + { + // 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."); + return gl::OutOfMemory() << "Device was lost while waiting for sync."; } - } - while (result == S_FALSE); + } while (result == S_FALSE); - return gl::Error(GL_NO_ERROR); -} - -SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, - HANDLE shareHandle, - GLenum backBufferFormat, - GLenum depthBufferFormat, - EGLint orientation) -{ - return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, - orientation); + return gl::NoError(); } -CompilerImpl *Renderer11::createCompiler() +bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const { - if (mRenderer11DeviceCaps.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); - } +#ifdef ANGLE_ENABLE_WINDOWS_STORE + return NativeWindow11WinRT::IsValidNativeWindow(window); +#else + return NativeWindow11Win32::IsValidNativeWindow(window); +#endif } -void *Renderer11::getD3DDevice() +NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const { - return reinterpret_cast<void*>(mDevice); +#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 } -gl::Error Renderer11::generateSwizzle(gl::Texture *texture) +egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, + IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const { - if (texture) + ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture); + if (texture == nullptr) { - TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); - ASSERT(textureD3D); - - TextureStorage *texStorage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&texStorage); - if (error.isError()) - { - return error; - } - - if (texStorage) - { - TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); - const gl::TextureState &textureState = texture->getTextureState(); - error = - storage11->generateSwizzles(textureState.swizzleRed, textureState.swizzleGreen, - textureState.swizzleBlue, textureState.swizzleAlpha); - if (error.isError()) - { - return error; - } - } + return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D"; } - return gl::Error(GL_NO_ERROR); -} - -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; - gl::Error error = textureD3D->getNativeTexture(&storage); - if (error.isError()) + ID3D11Device *textureDevice = nullptr; + texture->GetDevice(&textureDevice); + if (textureDevice != mDevice) { - return error; + SafeRelease(texture); + return egl::EglBadParameter() << "Texture's device does not match."; } + SafeRelease(textureDevice); - // Storage should exist, texture should be complete - ASSERT(storage); + D3D11_TEXTURE2D_DESC desc = {0}; + texture->GetDesc(&desc); + SafeRelease(texture); - if (type == gl::SAMPLER_PIXEL) + if (width) { - ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits); - - if (mForceSetPixelSamplerStates[index] || - memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerState, &dxSamplerState); - if (error.isError()) - { - return error; - } - - ASSERT(dxSamplerState != NULL); - mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - - mCurPixelSamplerStates[index] = samplerState; - } - - mForceSetPixelSamplerStates[index] = false; + *width = static_cast<EGLint>(desc.Width); } - else if (type == gl::SAMPLER_VERTEX) + if (height) { - ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits); - - if (mForceSetVertexSamplerStates[index] || - memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerState, &dxSamplerState); - if (error.isError()) - { - return error; - } - - ASSERT(dxSamplerState != NULL); - mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerState; - } - - mForceSetVertexSamplerStates[index] = false; + *height = static_cast<EGLint>(desc.Height); } - else UNREACHABLE(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - ID3D11ShaderResourceView *textureSRV = NULL; - - if (texture) + if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples) { - 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); - - TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); - - // Make sure to add the level offset for our tiny compressed texture workaround - gl::TextureState textureState = texture->getTextureState(); - textureState.baseLevel += storage11->getTopLevel(); - - error = storage11->getSRV(textureState, &textureSRV); - if (error.isError()) + // Both the texture and EGL config sample count may not be the same when multi-sampling + // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore, + // we must only check for a invalid match when the EGL config is non-zero or the texture is + // not one. + if (configuration->samples != 0 || desc.SampleDesc.Count != 1) { - return error; + return egl::EglBadParameter() << "Texture's sample count does not match."; } - - // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly - // missing the shader resource view - ASSERT(textureSRV != NULL); - - textureImpl->resetDirty(); } - - ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) || - (type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits)); - - mStateManager.setShaderResource(type, index, textureSRV); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setUniformBuffers(const gl::Data &data, - const std::vector<GLint> &vertexUniformBuffers, - const std::vector<GLint> &fragmentUniformBuffers) -{ - for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size(); uniformBufferIndex++) + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (desc.Format) { - GLint binding = vertexUniformBuffers[uniformBufferIndex]; - - if (binding == -1) - { - continue; - } - - const OffsetBindingPointer<gl::Buffer> &uniformBuffer = - data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); - ID3D11Buffer *constantBuffer; - - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) - { - constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - } - else - { - constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); - } - - if (!constantBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY); - } - - if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() || - mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || - mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) - { -#if defined(ANGLE_ENABLE_D3D11_1) - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) - { - UINT firstConstant = 0, numConstants = 0; - CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->VSSetConstantBuffers1( - getReservedVertexUniformBuffers() + - static_cast<unsigned int>(uniformBufferIndex), - 1, &constantBuffer, &firstConstant, &numConstants); - } - else -#endif - { - mDeviceContext->VSSetConstantBuffers( - getReservedVertexUniformBuffers() + - static_cast<unsigned int>(uniformBufferIndex), - 1, &constantBuffer); - } + 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; - mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); - mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset; - mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize; - } - } + default: + return egl::EglBadParameter() + << "Unknown client buffer texture format: " << desc.Format; } - for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size(); uniformBufferIndex++) + if (fboFormat) { - GLint binding = fragmentUniformBuffers[uniformBufferIndex]; - - if (binding == -1) - { - continue; - } - - const OffsetBindingPointer<gl::Buffer> &uniformBuffer = - data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); - ID3D11Buffer *constantBuffer; - - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) - { - constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - } - else - { - constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); - } - - if (!constantBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY); - } - - if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() || - mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || - mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) - { -#if defined(ANGLE_ENABLE_D3D11_1) - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) - { - UINT firstConstant = 0, numConstants = 0; - CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->PSSetConstantBuffers1( - getReservedFragmentUniformBuffers() + - static_cast<unsigned int>(uniformBufferIndex), - 1, &constantBuffer, &firstConstant, &numConstants); - } - else -#endif - { - mDeviceContext->PSSetConstantBuffers( - getReservedFragmentUniformBuffers() + - static_cast<unsigned int>(uniformBufferIndex), - 1, &constantBuffer); - } - - mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); - mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset; - mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize; - } - } + const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format); + *fboFormat = angleFormat.fboImplementationInternalFormat; } - return gl::Error(GL_NO_ERROR); + return egl::NoError(); } -gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode) +egl::Error Renderer11::validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const { - // Applies the render target surface, depth stencil surface, viewport rectangle and - // scissor rectangle to the renderer - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) + if (shareHandle == nullptr) { - return error; + return egl::EglBadParameter() << "NULL share handle."; } - // Set the present path state - const bool presentPathFastActive = - UsePresentPathFast(this, framebufferObject->getFirstColorbuffer()); - mStateManager.updatePresentPath(presentPathFastActive, - framebufferObject->getFirstColorbuffer()); - - // Setting viewport state - mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), - data.state->getFarPlane()); - - // Setting scissor state - mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - // Applying rasterizer state to D3D11 device - int samples = framebufferObject->getSamples(data); - gl::RasterizerState rasterizer = data.state->getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - error = mStateManager.setRasterizerState(rasterizer); - if (error.isError()) + ID3D11Resource *tempResource11 = nullptr; + HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + if (FAILED(result)) { - return error; + return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result); } - // Setting blend state - unsigned int mask = GetBlendSampleMask(data, samples); - error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(), - data.state->getBlendColor(), mask); - if (error.isError()) + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11); + SafeRelease(tempResource11); + + if (texture2D == nullptr) { - return error; + return egl::EglBadParameter() + << "Failed to query ID3D11Texture2D object from share handle."; } - // Setting depth stencil state - error = mStateManager.setDepthStencilState(*data.state); - return error; -} - -void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) -{ - mStateManager.syncState(state, bitmask); -} - -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) -{ - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + D3D11_TEXTURE2D_DESC desc = {0}; + texture2D->GetDesc(&desc); + SafeRelease(texture2D); - GLsizei minCount = 0; + EGLint width = attribs.getAsInt(EGL_WIDTH, 0); + EGLint height = attribs.getAsInt(EGL_HEIGHT, 0); + ASSERT(width != 0 && height != 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; - } + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps()); - // 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) + if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) || + desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1) { - primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + return egl::EglBadParameter() << "Invalid texture parameters in share handle texture."; } - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } - - return count >= minCount; + return egl::NoError(); } -gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) +SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation, + EGLint samples) { - return mStateManager.syncFramebuffer(framebuffer); + return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture, + backBufferFormat, depthBufferFormat, orientation, samples); } -gl::Error Renderer11::applyVertexBuffer(const gl::State &state, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances, - TranslatedIndexData *indexInfo) +void *Renderer11::getD3DDevice() { - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); - if (error.isError()) - { - return error; - } - - // 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; - } - return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), - indexInfo, numIndicesPerInstance); + return reinterpret_cast<void *>(mDevice); } -gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, - const GLvoid *indices, - GLsizei count, - GLenum mode, - GLenum type, - TranslatedIndexData *indexInfo) +bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count) { - gl::VertexArray *vao = data.state->getVertexArray(); - gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - gl::Error error = - mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, - data.state->isPrimitiveRestartEnabled()); - if (error.isError()) - { - return error; - } - - ID3D11Buffer *buffer = NULL; - DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - - if (indexInfo->storage) - { - Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage); - buffer = storage->getBuffer(BUFFER_USAGE_INDEX); - } - 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::Error(GL_NO_ERROR); -} + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) -{ - size_t numXFBBindings = 0; - bool requiresUpdate = false; + GLsizei minCount = 0; - if (state.isTransformFeedbackActiveUnpaused()) + switch (mode) { - const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); - numXFBBindings = transformFeedback->getIndexedBufferCount(); - ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); - - for (size_t i = 0; i < numXFBBindings; i++) + case GL_POINTS: { - const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i); - - ID3D11Buffer *d3dBuffer = NULL; - if (binding.get() != nullptr) - { - Buffer11 *storage = GetImplAs<Buffer11>(binding.get()); - d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - } + bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize(); - // TODO: mAppliedTFBuffers and friends should also be kept in a vector. - if (d3dBuffer != mAppliedTFBuffers[i] || binding.getOffset() != mAppliedTFOffsets[i]) + // 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 && !glState.isTransformFeedbackActiveUnpaused()) { - requiresUpdate = true; + // Notify developers of risking undefined behavior. + WARN() << "Point rendering without writing to gl_PointSize."; + return false; } - } - } - if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) - { - const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); - for (size_t i = 0; i < numXFBBindings; ++i) - { - const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i); - if (binding.get() != nullptr) + // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology + // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. + if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) { - Buffer11 *storage = GetImplAs<Buffer11>(binding.get()); - ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - - mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ? - static_cast<UINT>(binding.getOffset()) : -1; - mAppliedTFBuffers[i] = d3dBuffer; + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } else { - mAppliedTFBuffers[i] = NULL; - mCurrentD3DOffsets[i] = 0; + primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; } - mAppliedTFOffsets[i] = binding.getOffset(); + 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 = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3; + break; + case GL_TRIANGLE_STRIP: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3; + break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3; + break; + default: + UNREACHABLE(); + return false; + } - mAppliedNumXFBBindings = numXFBBindings; + mStateManager.setPrimitiveTopology(primitiveTopology); - mDeviceContext->SOSetTargets(static_cast<unsigned int>(numXFBBindings), mAppliedTFBuffers, - mCurrentD3DOffsets); - } + return count >= minCount; } -gl::Error Renderer11::drawArraysImpl(const gl::Data &data, - GLenum mode, - GLsizei count, - GLsizei instances) +gl::Error Renderer11::drawArrays(const gl::Context *context, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances) { - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); + const auto &glState = context->getGLState(); - if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused()) + if (!applyPrimitiveType(glState, mode, count)) + { + return gl::NoError(); + } + + DrawCallVertexParams vertexParams(startVertex, count, instances); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); + + if (glState.isTransformFeedbackActiveUnpaused()) + { + ANGLE_TRY(markTransformFeedbackUsage(context)); + } + + gl::Program *program = glState.getProgram(); + ASSERT(program != nullptr); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + + 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); + mStateManager.setPixelShader(nullptr); - if (instances > 0) + if (adjustedInstanceCount > 0) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } else { @@ -1673,203 +1561,330 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, } rx::ShaderExecutableD3D *pixelExe = nullptr; - gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); // Skip the draw call if rasterizer discard is enabled (or no fragment shader). - if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard) + if (!pixelExe || glState.getRasterizerState().rasterizerDiscard) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader(); - ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader()); // Retrieve the geometry shader. rx::ShaderExecutableD3D *geometryExe = nullptr; - error = - programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, mode, &geometryExe, + nullptr)); - ID3D11GeometryShader *geometryShader = - (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL); - mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); - ASSERT(geometryShader); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); + mStateManager.setGeometryShader( + &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader()); - if (instances > 0) + if (adjustedInstanceCount > 0) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } else { mDeviceContext->Draw(count, 0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } if (mode == GL_LINE_LOOP) { - return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances); + return drawLineLoop(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount); } if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); + return drawTriangleFan(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount); } bool useInstancedPointSpriteEmulation = programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation; - if (instances > 0) + if (mode != GL_POINTS || !useInstancedPointSpriteEmulation) { - if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + if (adjustedInstanceCount == 0) { - // 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++) - { - gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i); - if (error.isError()) - { - return error; - } - - mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); - } + mDeviceContext->Draw(count, 0); } else { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } + // This code should not be reachable by multi-view programs. + ASSERT(program->usesMultiview() == false); + // 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) + if (adjustedInstanceCount == 0) { mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + return gl::NoError(); } - else + + // 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++) { - mDeviceContext->Draw(count, 0); + ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i)); + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); } - return gl::Error(GL_NO_ERROR); + + // This required by updateVertexOffsets... above but is outside of the loop for speed. + mStateManager.invalidateVertexBuffer(); + return gl::NoError(); } -gl::Error Renderer11::drawElementsImpl(const gl::Data &data, - const TranslatedIndexData &indexInfo, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances) +gl::Error Renderer11::drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) { - int minIndex = static_cast<int>(indexInfo.indexRange.start); + const auto &glState = context->getGLState(); + + if (!applyPrimitiveType(glState, mode, count)) + { + return gl::NoError(); + } + + // Transform feedback is not allowed for DrawElements, this error should have been caught at the + // API validation layer. + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); + + const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>(); + + bool usePrimitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type); + DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances); + + ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, + usePrimitiveRestartWorkaround)); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); + + int startVertex = static_cast<int>(vertexParams.firstVertex()); + int baseVertex = -startVertex; + + const gl::Program *program = glState.getProgram(); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); if (mode == GL_LINE_LOOP) { - return drawLineLoop(data, count, type, indices, &indexInfo, instances); + return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount); } if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(data, count, type, indices, minIndex, instances); + return drawTriangleFan(context, count, type, indices, baseVertex, adjustedInstanceCount); } - const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - if (instances > 0) + const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + if (mode != GL_POINTS || !programD3D->usesInstancedPointSpriteEmulation()) { - if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + if (adjustedInstanceCount == 0) { - // 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++) - { - gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i); - if (error.isError()) - { - return error; - } - - mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0); - } + mDeviceContext->DrawIndexed(count, 0, baseVertex); } else { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, baseVertex, 0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } + // This code should not be reachable by multi-view programs. + ASSERT(program->usesMultiview() == false); + // 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. + // + // 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. + if (instances == 0) + { mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + return gl::NoError(); } - else + + // 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 = vertexParams.vertexCount(); + + // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets. + for (GLsizei i = 0; i < instances; i++) + { + ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i)); + mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0); + } + mStateManager.invalidateVertexBuffer(); + return gl::NoError(); +} + +gl::Error Renderer11::drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) +{ + const auto &glState = context->getGLState(); + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); + + if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1)) + { + return gl::NoError(); + } + + gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); + ASSERT(drawIndirectBuffer); + Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); + uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); + + if (!DrawCallNeedsTranslation(context, mode)) + { + DrawCallVertexParams vertexParams(0, 0, 0); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); + ID3D11Buffer *buffer = nullptr; + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer); + mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset)); + return gl::NoError(); + } + + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); + ASSERT(bufferData); + const gl::DrawArraysIndirectCommand *args = + reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset); + GLuint count = args->count; + GLuint instances = args->instanceCount; + GLuint first = args->first; + + DrawCallVertexParams vertexParams(first, count, instances); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(context, count, GL_NONE, nullptr, 0, instances); + } + if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(context, count, GL_NONE, nullptr, 0, instances); + } + + mDeviceContext->DrawInstanced(count, instances, 0, 0); + return gl::NoError(); +} + +gl::Error Renderer11::drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) +{ + const auto &glState = context->getGLState(); + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); + + if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1)) + { + return gl::NoError(); + } + + gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); + ASSERT(drawIndirectBuffer); + Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); + uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); + + // TODO(jmadill): Remove the if statement and compute indirect parameters lazily. + bool usePrimitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type); + + if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type)) + { + ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(), + usePrimitiveRestartWorkaround)); + DrawCallVertexParams vertexParams(0, 0, 0); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); + ID3D11Buffer *buffer = nullptr; + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer); + mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset)); + return gl::NoError(); + } + + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); + ASSERT(bufferData); + + const gl::DrawElementsIndirectCommand *cmd = + reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset); + GLsizei count = cmd->count; + GLuint instances = cmd->primCount; + GLuint firstIndex = cmd->firstIndex; + GLint baseVertex = cmd->baseVertex; + + // TODO(jmadill): Fix const cast. + const gl::Type &typeInfo = gl::GetTypeInfo(type); + const void *indices = + reinterpret_cast<const void *>(static_cast<uintptr_t>(firstIndex * typeInfo.bytes)); + gl::HasIndexRange lazyIndexRange(const_cast<gl::Context *>(context), count, type, indices); + + ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, + usePrimitiveRestartWorkaround)); + + DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances); + + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); + + int baseVertexLocation = -static_cast<int>(lazyIndexRange.getIndexRange().value().start); + + if (mode == GL_LINE_LOOP) { - mDeviceContext->DrawIndexed(count, 0, -minIndex); + return drawLineLoop(context, count, type, indices, baseVertexLocation, instances); } - return gl::Error(GL_NO_ERROR); + + if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(context, count, type, indices, baseVertexLocation, instances); + } + + mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0); + return gl::NoError(); } -gl::Error Renderer11::drawLineLoop(const gl::Data &data, +gl::Error Renderer11::drawLineLoop(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indexPointer, - const TranslatedIndexData *indexInfo, + const void *indexPointer, + int baseVertex, int instances) { - gl::VertexArray *vao = data.state->getVertexArray(); + const gl::State &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - const GLvoid *indices = indexPointer; + const void *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); + intptr_t offset = reinterpret_cast<intptr_t>(indices); - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); indices = bufferData + offset; } @@ -1877,7 +1892,8 @@ gl::Error Renderer11::drawLineLoop(const gl::Data &data, if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + gl::Error error = + mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mLineLoopIB); @@ -1888,92 +1904,71 @@ gl::Error Renderer11::drawLineLoop(const gl::Data &data, // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 0); - if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) + 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."); + return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for " + "GL_LINE_LOOP, too many indices required."; } GetLineLoopIndices(indices, type, static_cast<GLuint>(count), - data.state->isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); + glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); unsigned int spaceNeeded = static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size()); - gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); - void* mappedMemory = NULL; + void *mappedMemory = nullptr; unsigned int offset; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); // Copy over the converted index data. memcpy(mappedMemory, &mScratchIndexDataBuffer[0], sizeof(GLuint) * mScratchIndexDataBuffer.size()); - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mLineLoopIB->unmapBuffer()); - IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer()); + const d3d11::Buffer &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; - } + mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, 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); + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); } else { - mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation); + mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer11::drawTriangleFan(const gl::Data &data, +gl::Error Renderer11::drawTriangleFan(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indices, - int minIndex, + const void *indices, + int baseVertex, int instances) { - gl::VertexArray *vao = data.state->getVertexArray(); + const gl::State &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - const GLvoid *indexPointer = indices; + const void *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); + intptr_t offset = reinterpret_cast<intptr_t>(indices); - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); indexPointer = bufferData + offset; } @@ -1981,7 +1976,8 @@ gl::Error Renderer11::drawTriangleFan(const gl::Data &data, if (!mTriangleFanIB) { mTriangleFanIB = new StreamingIndexBufferInterface(this); - gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + gl::Error error = + mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mTriangleFanIB); @@ -1996,386 +1992,50 @@ gl::Error Renderer11::drawTriangleFan(const gl::Data &data, 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."); + return gl::OutOfMemory() << "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, " + "too many indices required."; } - GetTriFanIndices(indexPointer, type, count, data.state->isPrimitiveRestartEnabled(), + GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); const unsigned int spaceNeeded = static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); - gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); void *mappedMemory = nullptr; unsigned int offset; - error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); - error = mTriangleFanIB->unmapBuffer(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mTriangleFanIB->unmapBuffer()); - IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer()); + const d3d11::Buffer &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; - } + mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset); UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0); + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); } else { - mDeviceContext->DrawIndexed(indexCount, 0, -minIndex); + mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); } - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode) -{ - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - const auto &inputLayout = programD3D->getCachedInputLayout(); - - ShaderExecutableD3D *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); - if (error.isError()) - { - return error; - } - - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); - if (error.isError()) - { - return error; - } - - ShaderExecutableD3D *geometryExe = nullptr; - error = - programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr); - if (error.isError()) - { - return error; - } - - ID3D11VertexShader *vertexShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : NULL); - - ID3D11PixelShader *pixelShader = NULL; - // Skip pixel shader if we're doing rasterizer discard. - bool rasterizerDiscard = data.state->getRasterizerState().rasterizerDiscard; - if (!rasterizerDiscard) - { - pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : NULL); - } - - ID3D11GeometryShader *geometryShader = NULL; - bool transformFeedbackActive = data.state->isTransformFeedbackActiveUnpaused(); - if (transformFeedbackActive) - { - geometryShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : NULL); - } - else - { - geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL); - } - - bool dirtyUniforms = false; - - if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader) - { - mDeviceContext->VSSetShader(vertexShader, NULL, 0); - mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader); - dirtyUniforms = true; - } - - if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader) - { - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); - dirtyUniforms = true; - } - - if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader) - { - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader); - dirtyUniforms = true; - } - - if (dirtyUniforms) - { - programD3D->dirtyAllUniforms(); - } - - return gl::Error(GL_NO_ERROR); -} - -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); - UNUSED_ASSERTION_VARIABLE(result); - 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); - UNUSED_ASSERTION_VARIABLE(result); - 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(0, 1, &vertexConstantBuffer); - mCurrentVertexConstantBuffer = vertexConstantBuffer; - } - - if (mCurrentPixelConstantBuffer != pixelConstantBuffer) - { - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); - mCurrentPixelConstantBuffer = pixelConstantBuffer; - } - - // Driver uniforms - if (!mDriverConstantBufferVS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants11); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &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(1, 1, &mDriverConstantBufferVS); - } - - if (!mDriverConstantBufferPS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants11); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &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(1, 1, &mDriverConstantBufferPS); - } - - const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants(); - if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants11)) != 0) - { - ASSERT(mDriverConstantBufferVS != nullptr); - if (mDriverConstantBufferVS) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants, - 16, 0); - memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants11)); - } - } - - const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants(); - if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants11)) != 0) - { - ASSERT(mDriverConstantBufferPS != nullptr); - if (mDriverConstantBufferPS) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16, - 0); - memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants11)); - } - } - - // 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); - if (mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -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; - - mAppliedNumXFBBindings = static_cast<size_t>(-1); - - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - mAppliedTFBuffers[i] = NULL; - mAppliedTFOffsets[i] = 0; - } - - 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; + return gl::NoError(); } void Renderer11::releaseDeviceResources() { + mStateManager.deinitialize(); mStateCache.clear(); - mInputLayoutCache.clear(); - SafeDelete(mVertexDataManager); - SafeDelete(mIndexDataManager); SafeDelete(mLineLoopIB); SafeDelete(mTriangleFanIB); SafeDelete(mBlit); @@ -2383,9 +2043,9 @@ void Renderer11::releaseDeviceResources() SafeDelete(mTrim); SafeDelete(mPixelTransfer); - SafeRelease(mDriverConstantBufferVS); - SafeRelease(mDriverConstantBufferPS); - SafeRelease(mSyncQuery); + mSyncQuery.reset(); + + mCachedResolveTexture.reset(); } // set notify to true to broadcast a message to all contexts of the device loss @@ -2393,24 +2053,18 @@ 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); + isLost = d3d11::isDeviceLostError(result); if (isLost) { - // Log error if this is a new device lost event - if (mDeviceLost == false) - { - ERR("The D3D11 device was removed: 0x%08X", result); - } - - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; + ERR() << "The D3D11 device was removed, " << gl::FmtHR(result); } return isLost; @@ -2419,27 +2073,24 @@ bool Renderer11::testDeviceLost() 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"); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = + (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - if (D3D11CreateDevice == NULL) + if (D3D11CreateDevice == nullptr) { return false; } - ID3D11Device* dummyDevice; + ID3D11Device *dummyDevice; D3D_FEATURE_LEVEL dummyFeatureLevel; - ID3D11DeviceContext* dummyContext; + ID3D11DeviceContext *dummyContext; + UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0); 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); + nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(), + static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &dummyDevice, + &dummyFeatureLevel, &dummyContext); if (!mDevice || FAILED(result)) { @@ -2456,6 +2107,14 @@ void Renderer11::release() { RendererD3D::cleanup(); + mScratchMemoryBuffer.clear(); + + if (mAnnotator != nullptr) + { + gl::UninitializeDebugAnnotations(); + SafeDelete(mAnnotator); + } + releaseDeviceResources(); if (!mCreatedWithDeviceEXT) @@ -2468,9 +2127,8 @@ void Renderer11::release() SafeRelease(mDxgiFactory); SafeRelease(mDxgiAdapter); -#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mDeviceContext3); SafeRelease(mDeviceContext1); -#endif if (mDeviceContext) { @@ -2480,26 +2138,24 @@ void Renderer11::release() } SafeRelease(mDevice); -#if !defined(ANGLE_MINGW32_COMPAT) SafeRelease(mDebug); -#endif if (mD3d11Module) { FreeLibrary(mD3d11Module); - mD3d11Module = NULL; + mD3d11Module = nullptr; } if (mDxgiModule) { FreeLibrary(mDxgiModule); - mDxgiModule = NULL; + mDxgiModule = nullptr; } if (mDCompModule) { FreeLibrary(mDCompModule); - mDCompModule = NULL; + mDCompModule = nullptr; } mCompiler.release(); @@ -2515,12 +2171,10 @@ bool Renderer11::resetDevice() if (result.isError()) { - ERR("Could not reinitialize D3D11 device: %08X", result.getCode()); + ERR() << "Could not reinitialize D3D11 device: " << result; return false; } - mDeviceLost = false; - return true; } @@ -2531,8 +2185,10 @@ std::string Renderer11::getRendererDescription() const rendererString << mDescription; rendererString << " Direct3D11"; - rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); - rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); return rendererString.str(); } @@ -2540,12 +2196,12 @@ std::string Renderer11::getRendererDescription() const 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); + 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; } @@ -2605,7 +2261,7 @@ bool Renderer11::getShareHandleSupport() const // We only currently support share handles with BGRA surfaces, because // chrome needs BGRA. Once chrome fixes this, we should always support them. - if (!getRendererExtensions().textureFormatBGRA8888) + if (!getNativeExtensions().textureFormatBGRA8888) { mSupportsShareHandles = false; return false; @@ -2620,7 +2276,8 @@ bool Renderer11::getShareHandleSupport() const // Qt: we don't care about the 9_3 limitation #if 0 - // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. + // 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; @@ -2668,15 +2325,34 @@ bool Renderer11::getShareHandleSupport() const 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; + case D3D_FEATURE_LEVEL_11_1: + 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; } } @@ -2684,11 +2360,18 @@ 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; + case D3D_FEATURE_LEVEL_11_1: + 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; } } @@ -2696,15 +2379,22 @@ 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 ""; + case D3D_FEATURE_LEVEL_11_1: + 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 +const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const { if (!mWorkaroundsInitialized) { @@ -2715,42 +2405,31 @@ const WorkaroundsD3D &RendererD3D::getWorkarounds() const return mWorkarounds; } -gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImageInternal(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer(); + ASSERT(colorAttachment); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } + RenderTarget11 *sourceRenderTarget = nullptr; + ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget)); ASSERT(sourceRenderTarget); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); + const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView(); + ASSERT(source.valid()); - ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + const d3d11::RenderTargetView &dest = + GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); + ASSERT(dest.valid()); 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, colorbuffer); + const bool invertSource = UsePresentPathFast(this, colorAttachment); if (invertSource) { sourceArea.y = sourceSize.height - sourceRect.y; @@ -2760,226 +2439,267 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: 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 - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST, false); - if (error.isError()) - { - return error; - } + // Use nearest filtering because source and destination are the same size for the direct copy. + // Convert to the unsized format before calling copyTexture. + GLenum sourceFormat = colorAttachment->getFormat().info->format; + ANGLE_TRY(mBlit->copyTexture(context, source, sourceArea, sourceSize, sourceFormat, dest, + destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat), + GL_NEAREST, false, false, false)); - storage11->invalidateSwizzleCacheLevel(level); - - return gl::Error(GL_NO_ERROR); + 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) +gl::Error Renderer11::copyImage2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage); + ASSERT(storage11); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); + + storage11->markLevelDirty(level); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + return gl::NoError(); +} +gl::Error Renderer11::copyImageCube(const gl::Context *context, + 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 = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + storage11->markLevelDirty(level); - const bool invertSource = UsePresentPathFast(this, colorbuffer); - if (invertSource) - { - sourceArea.y = sourceSize.height - sourceRect.y; - sourceArea.height = -sourceArea.height; - } + return gl::NoError(); +} - gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); +gl::Error Renderer11::copyImage3D(const gl::Context *context, + 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); - // Use nearest filtering because source and destination are the same size for the direct - // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST, false); - if (error.isError()) - { - return error; - } + gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); - storage11->invalidateSwizzleCacheLevel(level); + storage11->markLevelDirty(level); - return gl::Error(GL_NO_ERROR); + 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) +gl::Error Renderer11::copyImage2DArray(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage); + ASSERT(storage11); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); + storage11->markLevelDirty(level); - TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage); - ASSERT(storage11); + return gl::NoError(); +} - gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); +gl::Error Renderer11::copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); - ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage); + ASSERT(sourceStorage11); - gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage); + ASSERT(destStorage11); - // Use nearest filtering because source and destination are the same size for the direct - // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST, false); - if (error.isError()) + // Check for fast path where a CopySubresourceRegion can be used. + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY && + source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format == destFormat && + sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat) { - return error; - } + const TextureHelper11 *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); - storage11->invalidateSwizzleCacheLevel(level); + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); - return gl::Error(GL_NO_ERROR); -} + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(context, &destResource)); -gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level) -{ - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; + 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->get(), destSubresource, destOffset.x, + destOffset.y, destOffset.z, sourceResource->get(), + sourceSubresource, &sourceBox); } - ASSERT(sourceRenderTarget); + else + { + const d3d11::SharedSRV *sourceSRV = nullptr; + ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV)); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel); + RenderTargetD3D *destRenderTargetD3D = nullptr; + ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D)); - TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); + RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D); - ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView(); + ASSERT(destRTV.valid()); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + 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 += sourceArea.height; + 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); + 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 - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST, false); - if (error.isError()) - { - return error; + // Use nearest filtering because source and destination are the same size for the direct + // copy + GLenum sourceFormat = source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format; + ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceSize, sourceFormat, + destRTV, destArea, destSize, nullptr, destFormat, GL_NEAREST, + false, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); } - storage11->invalidateSwizzleCacheLevel(level); + destStorage11->markLevelDirty(destLevel); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Renderer11::unapplyRenderTargets() +gl::Error Renderer11::copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) { - setOneTimeRenderTarget(NULL); -} + TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage); + ASSERT(destStorage11); -// When finished with this rendertarget, markAllStateDirty must be called. -void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) -{ - ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(context, &destResource)); - rtvArray[0] = renderTargetView; + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); - mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); + TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + ASSERT(sourceD3D); - // Do not preserve the serial for this one-time-use render target - for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) - { - mAppliedRTVs[rtIndex] = angle::DirtyPointer; - } - mAppliedDSV = angle::DirtyPointer; + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); + + TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage); + ASSERT(sourceStorage11); + + const TextureHelper11 *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); + + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); + + mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0, + sourceResource->get(), sourceSubresource, nullptr); + + return gl::NoError(); } -gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +gl::Error Renderer11::createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) { - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mRenderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps); - const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); + 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.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; + 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 @@ -2987,110 +2707,105 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G bool bindRTV = false, bindDSV = false, bindSRV = false; bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); - if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN); + + bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1; + if (isMultisampledDepthStencil && + !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs) { - // Multisample targets flagged for binding as depth stencil cannot also be - // flagged for binding as SRV, so make certain not to add the SRV flag for - // these targets. - bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + bindSRV = false; } - desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | - (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + 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 = 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); - } + TextureHelper11 texture; + ANGLE_TRY(allocateTexture(desc, formatInfo, &texture)); - ID3D11ShaderResourceView *srv = NULL; + d3d11::SharedSRV srv; + d3d11::SharedSRV blitSRV; 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.Format = formatInfo.srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MipLevels = 1; - result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); - if (FAILED(result)) + ANGLE_TRY(allocateResource(srvDesc, texture.get(), &srv)); + + if (formatInfo.blitSRVFormat != formatInfo.srvFormat) { - 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); + 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; + + ANGLE_TRY(allocateResource(blitSRVDesc, texture.get(), &blitSRV)); + } + else + { + blitSRV = srv.makeCopy(); } } 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.Format = formatInfo.dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D + : D3D11_DSV_DIMENSION_TEXTURE2DMS; dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; + dsvDesc.Flags = 0; - ID3D11DepthStencilView *dsv = NULL; - result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result); - } + d3d11::DepthStencilView dsv; + ANGLE_TRY(allocateResource(dsvDesc, texture.get(), &dsv)); - *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples); - - SafeRelease(dsv); + *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo, + width, height, 1, supportedSamples); } 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.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); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(allocateResource(rtvDesc, texture.get(), &rtv)); - if (formatInfo.dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { - const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - mDeviceContext->ClearRenderTargetView(rtv, clearValues); + const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues); } - *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples); - - SafeRelease(rtv); + *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format, + formatInfo, width, height, 1, supportedSamples); } else { UNREACHABLE(); } - - SafeRelease(texture); - SafeRelease(srv); } else { - *outRT = new TextureRenderTarget11(reinterpret_cast<ID3D11RenderTargetView*>(NULL), NULL, NULL, format, width, height, 1, supportedSamples); + *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(), + d3d11::SharedSRV(), d3d11::SharedSRV(), format, + d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), + width, height, 1, supportedSamples); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) @@ -3098,58 +2813,35 @@ gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTarg ASSERT(source != nullptr); RenderTargetD3D *newRT = nullptr; - gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), - source->getInternalFormat(), source->getSamples(), &newRT); - if (error.isError()) - { - return error; - } + 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(), + mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(), + 0, 0, 0, source11->getTexture().get(), source11->getSubresourceIndex(), nullptr); *outRT = newRT; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data) -{ - return new Framebuffer11(data, this); -} - -ShaderImpl *Renderer11::createShader(const gl::Shader::Data &data) -{ - return new ShaderD3D(data); -} - -ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) -{ - return new ProgramD3D(data, this); -} - -gl::Error Renderer11::loadExecutable(const void *function, +gl::Error Renderer11::loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) { + ShaderData shaderData(function, length); + switch (type) { - case SHADER_VERTEX: + case gl::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); - } + d3d11::VertexShader vertexShader; + d3d11::GeometryShader streamOutShader; + ANGLE_TRY(allocateResource(shaderData, &vertexShader)); if (!streamOutVaryings.empty()) { @@ -3163,88 +2855,80 @@ gl::Error Renderer11::loadExecutable(const void *function, 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>( + 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); - } + ANGLE_TRY(allocateResource(shaderData, &soDeclaration, &streamOutShader)); } - *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); + *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader), + std::move(streamOutShader)); } break; - case SHADER_PIXEL: + case gl::SHADER_FRAGMENT: { - 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); + d3d11::PixelShader pixelShader; + ANGLE_TRY(allocateResource(shaderData, &pixelShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader)); } break; - case SHADER_GEOMETRY: + case gl::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); + d3d11::GeometryShader geometryShader; + ANGLE_TRY(allocateResource(shaderData, &geometryShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader)); + } + break; + case gl::SHADER_COMPUTE: + { + d3d11::ComputeShader computeShader; + ANGLE_TRY(allocateResource(shaderData, &computeShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader)); } break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + default: + UNREACHABLE(); + return gl::InternalError(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) { - const char *profileType = NULL; + std::stringstream profileStream; + 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); + case gl::SHADER_VERTEX: + profileStream << "vs"; + break; + case gl::SHADER_FRAGMENT: + profileStream << "ps"; + break; + case gl::SHADER_GEOMETRY: + profileStream << "gs"; + break; + case gl::SHADER_COMPUTE: + profileStream << "cs"; + break; + default: + UNREACHABLE(); + return gl::InternalError(); } - std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str()); + profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + std::string profile = profileStream.str(); UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; @@ -3260,11 +2944,12 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, 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. + // 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, "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() != "") @@ -3276,26 +2961,26 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); } - D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; + D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}}; - ID3DBlob *binary = NULL; + // TODO(jmadill): Use ComPtr? + ID3DBlob *binary = nullptr; std::string debugInfo; - gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo); - if (error.isError()) - { - return error; - } + 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. + // 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); + *outExectuable = nullptr; + return gl::NoError(); } - error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - streamOutVaryings, separatedOutputBuffers, outExectuable); + gl::Error error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()), + binary->GetBufferSize(), type, streamOutVaryings, + separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -3308,12 +2993,17 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, (*outExectuable)->appendDebugInfo(debugInfo); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error Renderer11::ensureHLSLCompilerInitialized() +{ + return mCompiler.ensureInitialized(); } UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) { - return new UniformStorage11(this, storageSize); + return new UniformStorage11(storageSize); } VertexBuffer *Renderer11::createVertexBuffer() @@ -3326,45 +3016,20 @@ IndexBuffer *Renderer11::createIndexBuffer() return new IndexBuffer11(this); } -BufferImpl *Renderer11::createBuffer() -{ - Buffer11 *buffer = new Buffer11(this); - mAliveBuffers.insert(buffer); - return buffer; -} - -VertexArrayImpl *Renderer11::createVertexArray(const gl::VertexArray::Data &data) -{ - return new VertexArray11(data); -} - -QueryImpl *Renderer11::createQuery(GLenum type) +StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) { - return new Query11(this, type); -} - -FenceNVImpl *Renderer11::createFenceNV() -{ - return new FenceNV11(this); -} - -FenceSyncImpl *Renderer11::createFenceSync() -{ - return new FenceSync11(this); -} - -TransformFeedbackImpl* Renderer11::createTransformFeedback() -{ - return new TransformFeedbackD3D(); + return new StreamProducerNV12(this); } bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const { - ASSERT(getRendererExtensions().pixelBufferObject); + ASSERT(getNativeExtensions().pixelBufferObject); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mRenderer11DeviceCaps); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); + const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); + const d3d11::Format &d3d11FormatInfo = + d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps); // sRGB formats do not work with D3D11 buffer SRVs if (internalFormatInfo.colorEncoding == GL_SRGB) @@ -3385,7 +3050,19 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const } // We don't support formats which we can't represent without conversion - if (dxgiFormatInfo.internalFormat != internalFormat) + 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; } @@ -3393,11 +3070,17 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const return true; } -gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error Renderer11::fastCopyBufferToTexture(const gl::Context *context, + 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); + return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget, + destinationFormat, sourcePixelsType, destArea); } ImageD3D *Renderer11::createImage() @@ -3405,31 +3088,44 @@ ImageD3D *Renderer11::createImage() return new Image11(this); } -gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) +gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src) { Image11 *dest11 = GetAs<Image11>(dest); - Image11 *src11 = GetAs<Image11>(src); - return Image11::generateMipmap(dest11, src11); + Image11 *src11 = GetAs<Image11>(src); + return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps); } -gl::Error Renderer11::generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) +gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) { TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); ASSERT(storage11->isRenderTarget()); ASSERT(storage11->supportsNativeMipmapFunction()); - ID3D11ShaderResourceView *srv; - gl::Error error = storage11->getSRVLevels(textureState.baseLevel, textureState.maxLevel, &srv); - if (error.isError()) - { - return error; - } + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(), + textureState.getEffectiveMaxLevel(), &srv)); - mDeviceContext->GenerateMips(srv); + mDeviceContext->GenerateMips(srv->get()); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error Renderer11::copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + Image11 *dest11 = GetAs<Image11>(dest); + Image11 *src11 = GetAs<Image11>(source); + return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps); } TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) @@ -3438,53 +3134,75 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) return new TextureStorage11_2D(this, swapChain11); } -TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage) +TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) { - return new TextureStorage11_EGLImage(this, eglImage); + return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D)); } -TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +TextureStorage *Renderer11::createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) { - return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); + return new TextureStorage11_External(this, stream, desc); } -TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) { - return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, + hintLevelZeroOnly); } -TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) { - return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, + hintLevelZeroOnly); } -TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) { - return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, + levels); } -TextureImpl *Renderer11::createTexture(GLenum target) +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) { - switch(target) - { - case GL_TEXTURE_2D: return new TextureD3D_2D(this); - case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); - case GL_TEXTURE_3D: return new TextureD3D_3D(this); - case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); - default: - UNREACHABLE(); - } - - return NULL; + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, + levels); } -RenderbufferImpl *Renderer11::createRenderbuffer() +TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) { - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - return renderbuffer; + return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples, + fixedSampleLocations); } -gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment, +gl::Error Renderer11::readFromAttachment(const gl::Context *context, + const gl::FramebufferAttachment &srcAttachment, const gl::Rectangle &sourceArea, GLenum format, GLenum type, @@ -3497,17 +3215,11 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt const bool invertTexture = UsePresentPathFast(this, &srcAttachment); - RenderTargetD3D *renderTarget = nullptr; - gl::Error error = srcAttachment.getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + RenderTarget11 *rt11 = nullptr; + ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11)); + ASSERT(rt11->getTexture().valid()); - RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); - ASSERT(rt11->getTexture()); - - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + const TextureHelper11 &textureHelper = rt11->getTexture(); unsigned int sourceSubResource = rt11->getSubresourceIndex(); const gl::Extents &texSize = textureHelper.getExtents(); @@ -3535,52 +3247,42 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt if (safeArea.width == 0 || safeArea.height == 0) { // no work to do - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Extents safeSize(safeArea.width, safeArea.height, 1); - auto errorOrResult = CreateStagingTexture(textureHelper.getTextureType(), - textureHelper.getFormat(), safeSize, mDevice); - if (errorOrResult.isError()) - { - return errorOrResult.getError(); - } + TextureHelper11 stagingHelper; + ANGLE_TRY_RESULT( + createStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize, + StagingAccess::READ), + stagingHelper); - TextureHelper11 stagingHelper(errorOrResult.getResult()); 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) + if (textureHelper.is2D() && 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.MipLevels = 1; + resolveDesc.ArraySize = 1; resolveDesc.Format = textureHelper.getFormat(); - resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Count = 1; resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 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); - } + ANGLE_TRY( + allocateTexture(resolveDesc, textureHelper.getFormatSet(), &resolvedTextureHelper)); - mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(), + mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(), sourceSubResource, textureHelper.getFormat()); - resolvedTextureHelper = TextureHelper11::MakeAndReference(resolveTex2D); sourceSubResource = 0; srcTexture = &resolvedTextureHelper; @@ -3594,132 +3296,66 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt // Select the correct layer from a 3D attachment srcBox.front = 0; - if (textureHelper.getTextureType() == GL_TEXTURE_3D) + if (textureHelper.is3D()) { 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) - { - 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); - error = packPixels(stagingHelper, packParams, pixelsOut); - - invertTexturePack.pixelBuffer.set(nullptr); + mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(), + sourceSubResource, &srcBox); - return error; - } - else + gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack); + if (!invertTexture) { - PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, packBuffer, 0); return packPixels(stagingHelper, packParams, pixelsOut); } + + // 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 + gl::PixelPackState invertTexturePack; + invertTexturePack.alignment = pack.alignment; + invertTexturePack.reverseRowOrder = !pack.reverseRowOrder; + + PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, packBuffer, + 0); + gl::Error error = packPixels(stagingHelper, packParams, pixelsOut); + ANGLE_TRY(error); + return gl::NoError(); } gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper, const PackPixelsParams ¶ms, uint8_t *pixelsOut) { - ID3D11Resource *readResource = textureHelper.getResource(); + ID3D11Resource *readResource = textureHelper.get(); 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; - int inputPitch; - if (params.pack.reverseRowOrder) - { - source = static_cast<uint8_t*>(mapping.pData) + mapping.RowPitch * (params.area.height - 1); - inputPitch = -static_cast<int>(mapping.RowPitch); - } - else - { - source = static_cast<uint8_t*>(mapping.pData); - inputPitch = static_cast<int>(mapping.RowPitch); + return gl::OutOfMemory() << "Failed to map internal texture for reading, " << gl::FmtHR(hr); } - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureHelper.getFormat()); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); - if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type) - { - uint8_t *dest = pixelsOut + params.offset; - for (int y = 0; y < params.area.height; y++) - { - memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); - } - } - else - { - ColorCopyFunction fastCopyFunc = - dxgiFormatInfo.getFastCopyFunction(params.format, params.type); - GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - fastCopyFunc(src, dest); - } - } - } - else - { - ColorReadFunction colorReadFunction = dxgiFormatInfo.colorReadFunction; - ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type); - - uint8_t temp[16]; // Maximum size of any Color<T> type used. - static_assert(sizeof(temp) >= sizeof(gl::ColorF) && - sizeof(temp) >= sizeof(gl::ColorUI) && - sizeof(temp) >= sizeof(gl::ColorI), - "Unexpected size of gl::Color struct."); + uint8_t *source = static_cast<uint8_t *>(mapping.pData); + int inputPitch = static_cast<int>(mapping.RowPitch); - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + const auto &formatInfo = textureHelper.getFormatSet(); + ASSERT(formatInfo.format().glInternalFormat != GL_NONE); - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - colorReadFunction(src, temp); - colorWriteFunction(temp, dest); - } - } - } - } + PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut); mDeviceContext->Unmap(readResource, 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, +gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context, + const gl::Rectangle &readRectIn, const gl::Rectangle &drawRectIn, RenderTargetD3D *readRenderTarget, RenderTargetD3D *drawRenderTarget, @@ -3735,63 +3371,64 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, ASSERT(colorBlit != (depthBlit || stencilBlit)); RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget); - if (!drawRenderTarget) + if (!drawRenderTarget11) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); + return gl::OutOfMemory() + << "Failed to retrieve the internal draw render target from the draw framebuffer."; } - ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); - ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); + const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget); - if (!readRenderTarget) + if (!readRenderTarget11) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); + return gl::OutOfMemory() + << "Failed to retrieve the internal read render target from the read framebuffer."; } - ID3D11Resource *readTexture = NULL; - ID3D11ShaderResourceView *readSRV = NULL; - unsigned int readSubresource = 0; - if (readRenderTarget->getSamples() > 0) + TextureHelper11 readTexture; + unsigned int readSubresource = 0; + d3d11::SharedSRV readSRV; + + if (readRenderTarget->isMultisampled()) { - ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); - ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource); + ANGLE_TRY_RESULT( + resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit), + readTexture); - if (unresolvedTexture) + if (!stencilBlit) { - readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; + const auto &readFormatSet = readTexture.getFormatSet(); - SafeRelease(unresolvedTexture); + 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, NULL, &readSRV); - if (FAILED(hresult)) - { - SafeRelease(readTexture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer."); - } + ANGLE_TRY(allocateResource(viewDesc, readTexture.get(), &readSRV)); } } else { - readTexture = readRenderTarget11->getTexture(); - readTexture->AddRef(); + ASSERT(readRenderTarget11); + readTexture = readRenderTarget11->getTexture(); readSubresource = readRenderTarget11->getSubresourceIndex(); - readSRV = readRenderTarget11->getShaderResourceView(); - readSRV->AddRef(); + readSRV = readRenderTarget11->getBlitShaderResourceView().makeCopy(); + if (!readSRV.valid()) + { + ASSERT(depthBlit || stencilBlit); + readSRV = readRenderTarget11->getShaderResourceView().makeCopy(); + } + ASSERT(readSRV.valid()); } - if (!readTexture || !readSRV) - { - SafeRelease(readTexture); - SafeRelease(readSRV); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target."); - } + // Stencil blits don't use shaders. + ASSERT(readSRV.valid() || stencilBlit); - gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); - gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + 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 @@ -3801,8 +3438,32 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, // by internally scaling the read and draw rectangles. gl::Rectangle readRect = readRectIn; gl::Rectangle drawRect = drawRectIn; - auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) + + auto flip = [](int val) { return val >= 0 ? 1 : -1; }; + + if (readRect.x > readSize.width && readRect.width < 0) + { + int delta = readRect.x - readSize.width; + readRect.x -= delta; + readRect.width += delta; + + int drawDelta = delta * flip(drawRect.width); + drawRect.x += drawDelta; + drawRect.width -= drawDelta; + } + + if (readRect.y > readSize.height && readRect.height < 0) { + int delta = readRect.y - readSize.height; + readRect.y -= delta; + readRect.height += delta; + + int drawDelta = delta * flip(drawRect.height); + drawRect.y += drawDelta; + drawRect.height -= drawDelta; + } + + 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)); @@ -3818,8 +3479,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, drawRect.width -= drawOffset; } - auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) - { + 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)); @@ -3853,24 +3513,41 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, drawRect.height += drawOffset; } - bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); + if (readRect.x1() > readSize.width) + { + int delta = readRect.x1() - readSize.width; + readRect.width -= delta; + drawRect.width -= delta * flip(drawRect.width); + } + + if (readRect.y1() > readSize.height) + { + int delta = readRect.y1() - readSize.height; + readRect.height -= delta; + drawRect.height -= delta * flip(drawRect.height); + } + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr); - const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()); - const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat()); - const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + const auto &destFormatInfo = + gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat()); + const auto &srcFormatInfo = + gl::GetSizedInternalFormatInfo(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) && - (dxgiFormatInfo.redBits > 0); + colorMask.red = + (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0); colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && - (dxgiFormatInfo.greenBits > 0); + (nativeFormat.greenBits > 0); colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && - (dxgiFormatInfo.blueBits > 0); + (nativeFormat.blueBits > 0); colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && - (dxgiFormatInfo.alphaBits > 0); + (nativeFormat.alphaBits > 0); // We only currently support masking off the alpha channel. bool colorMaskingNeeded = colorMask.alpha; @@ -3884,18 +3561,19 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, 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 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 = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); + bool partialDSBlit = + (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit); - gl::Error result(GL_NO_ERROR); - - if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && + if (readRenderTarget11->getFormatSet().formatID == + drawRenderTarget11->getFormatSet().formatID && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) { @@ -3903,16 +3581,17 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, UINT dstY = drawRect.y; D3D11_BOX readBox; - readBox.left = readRect.x; - readBox.right = readRect.x + readRect.width; - readBox.top = readRect.y; + 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; + readBox.front = 0; + readBox.back = 1; if (scissorNeeded) { - // drawRect is guaranteed to have positive width and height because stretchRequired is false. + // 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) @@ -3937,11 +3616,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox // We also require complete framebuffer copies for depth-stencil blit. - D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox; - mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, - readTexture, readSubresource, pSrcBox); - result = gl::Error(GL_NO_ERROR); + mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, 0, + readTexture.get(), readSubresource, pSrcBox); } else { @@ -3950,47 +3628,56 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, if (depthBlit && stencilBlit) { - result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); + ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); } else if (depthBlit) { - result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, - scissor); + const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView(); + ASSERT(readSRV.valid()); + ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea, + drawSize, scissor)); } else if (stencilBlit) { - result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); + ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); } else { + const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView(); + // We don't currently support masking off any other channel than alpha bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha; - result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, - scissor, destFormatInfo.format, filter, maskOffAlpha); + ASSERT(readSRV.valid()); + ANGLE_TRY(mBlit->copyTexture( + context, readSRV, readArea, readSize, srcFormatInfo.format, drawRTV, drawArea, + drawSize, scissor, destFormatInfo.format, filter, maskOffAlpha, false, false)); } } - SafeRelease(readTexture); - SafeRelease(readSRV); - - return result; + return gl::NoError(); } bool Renderer11::isES3Capable() const { - return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2); -}; + return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2); +} + +RendererClass Renderer11::getRendererClass() const +{ + return RENDERER_D3D11; +} void Renderer11::onSwap() { // Send histogram updates every half hour const double kHistogramUpdateInterval = 30 * 60; - const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime(); + auto *platform = ANGLEPlatformCurrent(); + const double currentTime = platform->monotonicallyIncreasingTime(platform); const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; if (timeSinceLastUpdate > kHistogramUpdateInterval) @@ -4005,7 +3692,7 @@ void Renderer11::updateHistograms() // Update the buffer CPU memory histogram { size_t sizeSum = 0; - for (auto &buffer : mAliveBuffers) + for (const Buffer11 *buffer : mAliveBuffers) { sizeSum += buffer->getTotalCPUBufferMemoryBytes(); } @@ -4015,53 +3702,71 @@ void Renderer11::updateHistograms() } } +void Renderer11::onBufferCreate(const Buffer11 *created) +{ + mAliveBuffers.insert(created); +} + void Renderer11::onBufferDelete(const Buffer11 *deleted) { mAliveBuffers.erase(deleted); } -ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +gl::ErrorOrResult<TextureHelper11> Renderer11::resolveMultisampledTexture( + const gl::Context *context, + RenderTarget11 *renderTarget, + bool depth, + bool stencil) { - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); + if (depth && !stencil) + { + return mBlit->resolveDepth(context, renderTarget); + } - if (textureDesc.SampleDesc.Count > 1) + if (stencil) { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = textureDesc.Usage; - resolveDesc.BindFlags = textureDesc.BindFlags; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; + return mBlit->resolveStencil(context, renderTarget, depth); + } - ID3D11Texture2D *resolveTexture = NULL; - HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); - if (FAILED(result)) - { - ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); - return NULL; - } + const auto &formatSet = renderTarget->getFormatSet(); - mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); - return resolveTexture; - } - else + ASSERT(renderTarget->isMultisampled()); + const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView(); + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + sourceSRV.get()->GetDesc(&sourceSRVDesc); + ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS); + + if (!mCachedResolveTexture.valid() || + mCachedResolveTexture.getExtents().width != renderTarget->getWidth() || + mCachedResolveTexture.getExtents().height != renderTarget->getHeight() || + mCachedResolveTexture.getFormat() != formatSet.texFormat) { - source->AddRef(); - return source; + 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; + + ANGLE_TRY(allocateTexture(resolveDesc, formatSet, &mCachedResolveTexture)); } + + mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0, + renderTarget->getTexture().get(), + renderTarget->getSubresourceIndex(), formatSet.texFormat); + return mCachedResolveTexture; } bool Renderer11::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; + adapterLuid->LowPart = 0; if (!mDxgiAdapter) { @@ -4078,45 +3783,70 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -VertexConversionType Renderer11::getVertexConversionType(gl::VertexFormatType vertexFormatType) const +VertexConversionType Renderer11::getVertexConversionType( + gl::VertexFormatType vertexFormatType) const { - return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).conversionType; + return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel) + .conversionType; } GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const { - return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).nativeFormat).componentType; + const auto &format = + d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel); + return d3d11::GetComponentType(format.nativeFormat); } -void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, - gl::Extensions *outExtensions, gl::Limitations *outLimitations) const +gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired( + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const { - d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, - outExtensions, outLimitations); -} + if (!attrib.enabled) + { + return 16u; + } -WorkaroundsD3D Renderer11::generateWorkarounds() const -{ - return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel); + unsigned int elementCount = 0; + const unsigned int divisor = binding.getDivisor(); + if (instances == 0 || divisor == 0) + { + elementCount = count; + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), 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::OutOfMemory() << "New vertex buffer size would result in an overflow."; + } + + return elementSize * elementCount; } -void Renderer11::createAnnotator() +void Renderer11::generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const { - // 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 + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, + outExtensions, outLimitations); } -gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +angle::WorkaroundsD3D Renderer11::generateWorkarounds() const { - return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd); + return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription); } egl::Error Renderer11::getEGLDevice(DeviceImpl **device) @@ -4136,6 +3866,224 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device) } *device = static_cast<DeviceImpl *>(mEGLDevice); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); +} + +ContextImpl *Renderer11::createContext(const gl::ContextState &state) +{ + return new Context11(state, this); +} + +FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + return new Framebuffer11(state, this); +} + +gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut) +{ + if (!mScratchMemoryBuffer.get(requestedSize, bufferOut)) + { + return gl::OutOfMemory() << "Failed to allocate internal buffer."; + } + return gl::NoError(); +} + +gl::Version Renderer11::getMaxSupportedESVersion() const +{ + return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel); +} + +gl::DebugAnnotator *Renderer11::getAnnotator() +{ + return mAnnotator; +} + +gl::Error Renderer11::applyComputeShader(const gl::Context *context) +{ + ANGLE_TRY(ensureHLSLCompilerInitialized()); + + const auto &glState = context->getGLState(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + ShaderExecutableD3D *computeExe = nullptr; + ANGLE_TRY(programD3D->getComputeExecutable(&computeExe)); + ASSERT(computeExe != nullptr); + + mStateManager.setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader()); + ANGLE_TRY(mStateManager.applyComputeUniforms(programD3D)); + + return gl::NoError(); +} + +gl::Error Renderer11::dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); + ANGLE_TRY(applyComputeShader(context)); + + mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); + + return gl::NoError(); +} + +gl::ErrorOrResult<TextureHelper11> Renderer11::createStagingTexture( + ResourceType textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess) +{ + if (textureType == ResourceType::Texture2D) + { + 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; + } + + TextureHelper11 stagingTex; + ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex)); + return stagingTex; + } + ASSERT(textureType == ResourceType::Texture3D); + + 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; + + TextureHelper11 stagingTex; + ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex)); + return stagingTex; +} + +gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE2D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut) +{ + d3d11::Texture2D texture; + ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture)); + textureOut->init(std::move(texture), desc, format); + return gl::NoError(); +} + +gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE3D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut) +{ + d3d11::Texture3D texture; + ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture)); + textureOut->init(std::move(texture), desc, format); + return gl::NoError(); +} + +gl::Error Renderer11::getBlendState(const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState) +{ + return mStateCache.getBlendState(this, key, outBlendState); +} + +gl::Error Renderer11::getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState) +{ + return mStateCache.getRasterizerState(this, rasterState, scissorEnabled, outRasterizerState); +} + +gl::Error Renderer11::getDepthStencilState(const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState) +{ + return mStateCache.getDepthStencilState(this, dsState, outDSState); +} + +gl::Error Renderer11::getSamplerState(const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState) +{ + return mStateCache.getSamplerState(this, samplerState, outSamplerState); +} + +gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) +{ + RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); + + if (rt11->getDepthStencilView().valid()) + { + const auto &format = rt11->getFormatSet(); + const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) | + (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0); + mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags, + clearDepthValue, + static_cast<UINT8>(clearStencilValue)); + return gl::NoError(); + } + + ASSERT(rt11->getRenderTargetView().valid()); + ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get(); + + // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx + ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv)); + + const auto &d3d11Format = rt11->getFormatSet(); + const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat()); + + gl::ColorF safeClearColor = clearColorValue; + + if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0) + { + safeClearColor.alpha = 1.0f; + } + + mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red); + return gl::NoError(); +} + +bool Renderer11::canSelectViewInVertexShader() const +{ + return !getWorkarounds().selectViewInGeometryShader && + getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader; } + +gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context) +{ + const gl::State &glState = context->getGLState(); + const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); + for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) + { + const gl::OffsetBindingPointer<gl::Buffer> &binding = + transformFeedback->getIndexedBuffer(i); + if (binding.get() != nullptr) + { + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get()); + ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context)); + } + } + + return gl::NoError(); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index b4e7761ffc..a8c24e681b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -14,13 +14,14 @@ #include "libANGLE/AttributeMap.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/d3d/HLSLCompiler.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.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/ResourceManager11.h" #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -28,36 +29,46 @@ class FramebufferAttachment; struct ImageIndex; } -struct ID3D11DeviceContext1; - namespace rx { - -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; class Blit11; class Buffer11; class Clear11; +class Context11; +class IndexDataManager; +struct PackPixelsParams; class PixelTransfer11; class RenderTarget11; +class StreamingIndexBufferInterface; class Trim11; -struct PackPixelsParams; +class VertexDataManager; struct Renderer11DeviceCaps { + 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 + bool supportsDXGI1_2; // Support for DXGI 1.2 + bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView + bool supportsConstantBufferOffsets; // Support for Constant buffer offset + bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader + // stage. + bool supportsMultisampledDepthStencilSRVs; // D3D feature level 10.0 no longer allows creation + // of textures with both the bind SRV and DSV flags + // when multisampled. Textures will need to be + // resolved before reading. crbug.com/656989 + UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM + UINT B5G6R5maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G6R5_UNORM + UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM + UINT B4G4R4A4maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B4G4R4A4_UNORM + UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM + UINT B5G5R5A1maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G5R5A1_UNORM + Optional<LARGE_INTEGER> driverVersion; // Four-part driver version number. }; enum { - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 }; @@ -103,172 +114,244 @@ class Renderer11 : public RendererD3D { public: explicit Renderer11(egl::Display *display); - virtual ~Renderer11(); + ~Renderer11() override; egl::Error initialize() override; - virtual bool resetDevice(); + bool resetDevice() override; - egl::ConfigSet generateConfigs() const override; + egl::ConfigSet generateConfigs() override; void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; - gl::Error flush() override; - gl::Error finish() override; + ContextImpl *createContext(const gl::ContextState &state) override; + + gl::Error flush(); + gl::Error finish(); - SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + 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; - - CompilerImpl *createCompiler() override; - - virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - gl::Error setUniformBuffers(const gl::Data &data, - const std::vector<GLint> &vertexUniformBuffers, - const std::vector<GLint> &fragmentUniformBuffers) override; - - gl::Error updateState(const gl::Data &data, GLenum drawMode) override; - - virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize); - gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - gl::Error applyUniforms(const ProgramD3D &programD3D, - GLenum drawMode, - const std::vector<D3DUniform *> &uniformArray) override; - virtual gl::Error applyVertexBuffer(const gl::State &state, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances, - TranslatedIndexData *indexInfo); - gl::Error applyIndexBuffer(const gl::Data &data, - const GLvoid *indices, - GLsizei count, - GLenum mode, - GLenum type, - TranslatedIndexData *indexInfo) override; - void applyTransformFeedbackBuffers(const gl::State &state) override; + EGLint orientation, + EGLint samples) override; + egl::Error getD3DTextureInfo(const egl::Config *configuration, + 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; + + bool applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count); // lost device bool testDeviceLost() override; bool testDeviceResettable() override; - std::string getRendererDescription() const override; + std::string getRendererDescription() const; DeviceIdentifier getAdapterIdentifier() const override; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getReservedVertexUniformBuffers() const; - virtual unsigned int getReservedFragmentUniformBuffers() const; + unsigned int getReservedVertexUniformVectors() const; + unsigned int getReservedFragmentUniformVectors() const; + unsigned int getReservedVertexUniformBuffers() const; + unsigned int getReservedFragmentUniformBuffers() const; bool getShareHandleSupport() const; - virtual int getMajorShaderModel() const; + bool getNV12TextureSupport() const; + + int getMajorShaderModel() const override; int getMinorShaderModel() const override; std::string getShaderModelSuffix() const override; // Pixel operations - virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyImage2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImageCube(const gl::Context *context, + 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::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImage2DArray(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + + gl::Error copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + gl::Error copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) override; // RenderTarget creation - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + gl::Error createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) override; gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; - // Framebuffer creation - FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; - - // Shader creation - ShaderImpl *createShader(const gl::Shader::Data &data) override; - ProgramImpl *createProgram(const gl::Program::Data &data) override; - // Shader operations - gl::Error loadExecutable(const void *function, + gl::Error loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) override; gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) override; + gl::Error ensureHLSLCompilerInitialized() override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations - virtual ImageD3D *createImage(); - gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; - gl::Error generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) override; - virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); - TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override; - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - - // Texture creation - virtual TextureImpl *createTexture(GLenum target); - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer(); - - // Buffer creation - virtual BufferImpl *createBuffer(); - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - - // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceNVImpl *createFenceNV(); - virtual FenceSyncImpl *createFenceSync(); - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback(); + ImageD3D *createImage() override; + gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) override; + gl::Error copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) 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; + TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) 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; }; - DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - - RenderStateCache &getStateCache() { return mStateCache; } + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + + gl::Error getBlendState(const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState); + gl::Error getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState); + gl::Error getSamplerState(const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState); Blit11 *getBlitter() { return mBlit; } Clear11 *getClearer() { return mClear; } + gl::DebugAnnotator *getAnnotator(); // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override; + gl::Error fastCopyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) override; - void markAllStateDirty(); - void unapplyRenderTargets(); - void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); 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; + VertexConversionType getVertexConversionType( + gl::VertexFormatType vertexFormatType) const override; GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; - gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. + gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const override; + + gl::Error readFromAttachment(const gl::Context *context, + const gl::FramebufferAttachment &srcAttachment, const gl::Rectangle &sourceArea, GLenum format, GLenum type, @@ -276,145 +359,175 @@ class Renderer11 : public RendererD3D 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); + gl::Error blitRenderbufferRect(const gl::Context *context, + 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() { return mRenderer11DeviceCaps; }; + const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }; - RendererClass getRendererClass() const override { return RENDERER_D3D11; } - InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + RendererClass getRendererClass() const override; StateManager11 *getStateManager() { return &mStateManager; } void onSwap(); + void onBufferCreate(const Buffer11 *created); void onBufferDelete(const Buffer11 *deleted); egl::Error getEGLDevice(DeviceImpl **device) override; - protected: - void createAnnotator() override; - gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; - gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override; + gl::Error drawArrays(const gl::Context *context, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances); - void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; + gl::Error drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances); + + gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect); + gl::Error drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect); + + // Necessary hack for default framebuffers in D3D. + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + gl::Error getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut); + + gl::Version getMaxSupportedESVersion() const override; + + gl::Error dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ); + gl::Error applyComputeShader(const gl::Context *context); + + gl::ErrorOrResult<TextureHelper11> createStagingTexture(ResourceType textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess); + + template <typename DescT, typename ResourceT> + gl::Error allocateResource(const DescT &desc, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, &desc, nullptr, resourceOut); + } + + template <typename DescT, typename InitDataT, typename ResourceT> + gl::Error allocateResource(const DescT &desc, InitDataT *initData, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, &desc, initData, resourceOut); + } + + template <typename InitDataT, typename ResourceT> + gl::Error allocateResourceNoDesc(InitDataT *initData, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, nullptr, initData, resourceOut); + } + + template <typename DescT> + gl::Error allocateTexture(const DescT &desc, + const d3d11::Format &format, + TextureHelper11 *textureOut) + { + return allocateTexture(desc, format, nullptr, textureOut); + } + + gl::Error allocateTexture(const D3D11_TEXTURE2D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut); + + gl::Error allocateTexture(const D3D11_TEXTURE3D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut); + + gl::Error clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) override; + + bool canSelectViewInVertexShader() const override; private: - gl::Error drawArraysImpl(const gl::Data &data, - GLenum mode, - GLsizei count, - GLsizei instances) override; - gl::Error drawElementsImpl(const gl::Data &data, - const TranslatedIndexData &indexInfo, - GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLsizei instances) override; - - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions, gl::Limitations *outLimitations) const override; - WorkaroundsD3D generateWorkarounds() const override; + angle::WorkaroundsD3D generateWorkarounds() const override; - gl::Error drawLineLoop(const gl::Data &data, + gl::Error drawLineLoop(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indices, - const TranslatedIndexData *indexInfo, + const void *indices, + int baseVertex, int instances); - gl::Error drawTriangleFan(const gl::Data &data, + gl::Error drawTriangleFan(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indices, - int minIndex, + const void *indices, + int baseVertex, int instances); - ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + gl::ErrorOrResult<TextureHelper11> resolveMultisampledTexture(const gl::Context *context, + RenderTarget11 *renderTarget, + bool depth, + bool stencil); void populateRenderer11DeviceCaps(); void updateHistograms(); - HMODULE mD3d11Module; - HMODULE mDxgiModule; - HMODULE mDCompModule; - std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels; - D3D_DRIVER_TYPE mRequestedDriverType; - bool mCreatedWithDeviceEXT; - DeviceD3D *mEGLDevice; + gl::Error copyImageInternal(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget); - HLSLCompiler mCompiler; + gl::SupportedSampleSet generateSampleSetForEGLConfig( + const gl::TextureCaps &colorBufferFormatCaps, + const gl::TextureCaps &depthStencilBufferFormatCaps) const; + HRESULT callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug); egl::Error initializeD3DDevice(); - void initializeDevice(); + egl::Error initializeDevice(); void releaseDeviceResources(); void release(); d3d11::ANGLED3D11DeviceType getDeviceType() const; - RenderStateCache mStateCache; + gl::Error markTransformFeedbackUsage(const gl::Context *context); - // current render target states - uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - uintptr_t mAppliedDSV; + HMODULE mD3d11Module; + HMODULE mDxgiModule; + HMODULE mDCompModule; + std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels; + D3D_DRIVER_TYPE mRequestedDriverType; + bool mCreateDebugDevice; + bool mCreatedWithDeviceEXT; + DeviceD3D *mEGLDevice; - // Currently applied sampler states - std::vector<bool> mForceSetVertexSamplerStates; - std::vector<gl::SamplerState> mCurVertexSamplerStates; + HLSLCompiler mCompiler; - std::vector<bool> mForceSetPixelSamplerStates; - std::vector<gl::SamplerState> mCurPixelSamplerStates; + RenderStateCache mStateCache; 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 - size_t mAppliedNumXFBBindings; - ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers - // in use for streamout - GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified - // buffer offsets to transform feedback - // buffers - UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets, - // which may differ from GLs, due - // to different append behavior - - // Currently applied shaders - uintptr_t mAppliedVertexShader; - uintptr_t mAppliedGeometryShader; - uintptr_t mAppliedPixelShader; - - dx_VertexConstants11 mAppliedVertexConstants; - ID3D11Buffer *mDriverConstantBufferVS; - 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; - 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; @@ -429,10 +542,10 @@ class Renderer11 : public RendererD3D Trim11 *mTrim; // Sync query - ID3D11Query *mSyncQuery; + d3d11::Query mSyncQuery; // Created objects state tracking - std::set<const Buffer11*> mAliveBuffers; + std::set<const Buffer11 *> mAliveBuffers; double mLastHistogramUpdateTime; @@ -440,18 +553,24 @@ class Renderer11 : public RendererD3D Renderer11DeviceCaps mRenderer11DeviceCaps; ID3D11DeviceContext *mDeviceContext; ID3D11DeviceContext1 *mDeviceContext1; + ID3D11DeviceContext3 *mDeviceContext3; IDXGIAdapter *mDxgiAdapter; DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; - DXGIFactory *mDxgiFactory; -#if !defined(ANGLE_MINGW32_COMPAT) + IDXGIFactory *mDxgiFactory; ID3D11Debug *mDebug; -#endif std::vector<GLuint> mScratchIndexDataBuffer; + angle::ScratchBuffer mScratchMemoryBuffer; + + gl::DebugAnnotator *mAnnotator; + mutable Optional<bool> mSupportsShareHandles; + ResourceManager11 mResourceManager11; + + TextureHelper11 mCachedResolveTexture; }; -} -#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp new file mode 100644 index 0000000000..c228380a34 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp @@ -0,0 +1,533 @@ +// +// Copyright 2017 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. +// +// ResourceManager11: +// Centralized point of allocation for all D3D11 Resources. + +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +namespace +{ + +constexpr uint8_t kDebugInitTextureDataValue = 0x48; +constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f}; +constexpr FLOAT kDebugDepthInitValue = 0.2f; +constexpr UINT8 kDebugStencilInitValue = 3; + +uint64_t ComputeMippedMemoryUsage(unsigned int width, + unsigned int height, + unsigned int depth, + uint64_t pixelSize, + unsigned int mipLevels) +{ + uint64_t sizeSum = 0; + + for (unsigned int level = 0; level < mipLevels; ++level) + { + unsigned int mipWidth = std::max(width >> level, 1u); + unsigned int mipHeight = std::max(height >> level, 1u); + unsigned int mipDepth = std::max(depth >> level, 1u); + sizeSum += static_cast<uint64_t>(mipWidth * mipHeight * mipDepth) * pixelSize; + } + + return sizeSum; +} + +uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc) +{ + ASSERT(desc); + uint64_t pixelBytes = + static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes); + return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels); +} + +uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc) +{ + ASSERT(desc); + uint64_t pixelBytes = + static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes); + return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes, + desc->MipLevels); +} + +uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc) +{ + ASSERT(desc); + return static_cast<uint64_t>(desc->ByteWidth); +} + +template <typename T> +uint64_t ComputeMemoryUsage(const T *desc) +{ + return 0; +} + +template <ResourceType ResourceT> +uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource) +{ + auto *typedResource = static_cast<GetD3D11Type<ResourceT> *>(genericResource); + GetDescType<ResourceT> desc; + typedResource->GetDesc(&desc); + return ComputeMemoryUsage(&desc); +} + +uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource) +{ + switch (resourceType) + { + case ResourceType::Texture2D: + return ComputeGenericMemoryUsage<ResourceType::Texture2D>(resource); + case ResourceType::Texture3D: + return ComputeGenericMemoryUsage<ResourceType::Texture3D>(resource); + case ResourceType::Buffer: + return ComputeGenericMemoryUsage<ResourceType::Buffer>(resource); + + default: + return 0; + } +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_BLEND_DESC *desc, + void * /*initData*/, + ID3D11BlendState **blendState) +{ + return device->CreateBlendState(desc, blendState); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_BUFFER_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Buffer **buffer) +{ + return device->CreateBuffer(desc, initData, buffer); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11ComputeShader **resourceOut) +{ + return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_DEPTH_STENCIL_DESC *desc, + void * /*initData*/, + ID3D11DepthStencilState **resourceOut) +{ + return device->CreateDepthStencilState(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_DEPTH_STENCIL_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11DepthStencilView **resourceOut) +{ + return device->CreateDepthStencilView(resource, desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData, + ID3D11GeometryShader **resourceOut) +{ + if (initData) + { + return device->CreateGeometryShaderWithStreamOutput( + desc->get(), desc->size(), initData->data(), static_cast<UINT>(initData->size()), + nullptr, 0, 0, nullptr, resourceOut); + } + else + { + return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut); + } +} + +HRESULT CreateResource(ID3D11Device *device, + const InputElementArray *desc, + const ShaderData *initData, + ID3D11InputLayout **resourceOut) +{ + return device->CreateInputLayout(desc->get(), static_cast<UINT>(desc->size()), initData->get(), + initData->size(), resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11PixelShader **resourceOut) +{ + return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_QUERY_DESC *desc, + void * /*initData*/, + ID3D11Query **resourceOut) +{ + return device->CreateQuery(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_RASTERIZER_DESC *desc, + void * /*initData*/, + ID3D11RasterizerState **rasterizerState) +{ + return device->CreateRasterizerState(desc, rasterizerState); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_RENDER_TARGET_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11RenderTargetView **renderTargetView) +{ + return device->CreateRenderTargetView(resource, desc, renderTargetView); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_SAMPLER_DESC *desc, + void * /*initData*/, + ID3D11SamplerState **resourceOut) +{ + return device->CreateSamplerState(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_SHADER_RESOURCE_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11ShaderResourceView **resourceOut) +{ + return device->CreateShaderResourceView(resource, desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_TEXTURE2D_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Texture2D **texture) +{ + return device->CreateTexture2D(desc, initData, texture); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_TEXTURE3D_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Texture3D **texture) +{ + return device->CreateTexture3D(desc, initData, texture); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11VertexShader **resourceOut) +{ + return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_D16_UNORM; + case DXGI_FORMAT_R24G8_TYPELESS: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_D32_FLOAT; + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + default: + return dxgiFormat; + } +} + +template <typename DescT, typename ResourceT> +gl::Error ClearResource(Renderer11 *renderer, const DescT *desc, ResourceT *texture) +{ + // No-op. + return gl::NoError(); +} + +template <> +gl::Error ClearResource(Renderer11 *renderer, + const D3D11_TEXTURE2D_DESC *desc, + ID3D11Texture2D *texture) +{ + ID3D11DeviceContext *context = renderer->getDeviceContext(); + + if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Flags = 0; + dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format); + + const auto &format = d3d11_angle::GetFormat(dsvDesc.Format); + UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) | + (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0); + + // Must process each mip level individually. + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + if (desc->SampleDesc.Count == 0) + { + dsvDesc.Texture2D.MipSlice = mipLevel; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } + + d3d11::DepthStencilView dsv; + ANGLE_TRY(renderer->allocateResource(dsvDesc, texture, &dsv)); + + context->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue, + kDebugStencilInitValue); + } + } + else + { + ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0); + d3d11::RenderTargetView rtv; + ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv)); + + context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue); + } + + return gl::NoError(); +} + +template <> +gl::Error ClearResource(Renderer11 *renderer, + const D3D11_TEXTURE3D_DESC *desc, + ID3D11Texture3D *texture) +{ + ID3D11DeviceContext *context = renderer->getDeviceContext(); + + ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0); + ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0); + + d3d11::RenderTargetView rtv; + ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv)); + + context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue); + return gl::NoError(); +} + +#define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) #RESTYPE, + +constexpr std::array<const char *, NumResourceTypes> kResourceTypeNames = { + {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}}; +static_assert(kResourceTypeNames[NumResourceTypes - 1] != nullptr, + "All members must be initialized."); + +} // anonymous namespace + +// ResourceManager11 Implementation. +ResourceManager11::ResourceManager11() + : mInitializeAllocations(false), + mAllocatedResourceCounts({{}}), + mAllocatedResourceDeviceMemory({{}}) +{ +} + +ResourceManager11::~ResourceManager11() +{ + for (size_t count : mAllocatedResourceCounts) + { + ASSERT(count == 0); + } + + for (uint64_t memorySize : mAllocatedResourceDeviceMemory) + { + ASSERT(memorySize == 0); + } +} + +template <typename T> +gl::Error ResourceManager11::allocate(Renderer11 *renderer, + const GetDescFromD3D11<T> *desc, + GetInitDataFromD3D11<T> *initData, + Resource11<T> *resourceOut) +{ + ID3D11Device *device = renderer->getDevice(); + T *resource = nullptr; + + GetInitDataFromD3D11<T> *shadowInitData = initData; + if (!shadowInitData && mInitializeAllocations) + { + shadowInitData = createInitDataIfNeeded<T>(desc); + } + + HRESULT hr = CreateResource(device, desc, shadowInitData, &resource); + if (FAILED(hr)) + { + ASSERT(!resource); + if (d3d11::isDeviceLostError(hr)) + { + renderer->notifyDeviceLost(); + } + return gl::OutOfMemory() << "Error allocating " + << std::string(kResourceTypeNames[ResourceTypeIndex<T>()]) << ". " + << gl::FmtHR(hr); + } + + if (!shadowInitData && mInitializeAllocations) + { + ANGLE_TRY(ClearResource(renderer, desc, resource)); + } + + ASSERT(resource); + incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc)); + *resourceOut = std::move(Resource11<T>(resource, this)); + return gl::NoError(); +} + +void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize) +{ + size_t typeIndex = ResourceTypeIndex(resourceType); + + mAllocatedResourceCounts[typeIndex]++; + mAllocatedResourceDeviceMemory[typeIndex] += memorySize; + + // This checks for integer overflow. + ASSERT(mAllocatedResourceCounts[typeIndex] > 0); + ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize); +} + +void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize) +{ + size_t typeIndex = ResourceTypeIndex(resourceType); + + ASSERT(mAllocatedResourceCounts[typeIndex] > 0); + mAllocatedResourceCounts[typeIndex]--; + ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize); + mAllocatedResourceDeviceMemory[typeIndex] -= memorySize; +} + +void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource) +{ + ASSERT(resource); + decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource)); +} + +template <> +const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>( + const D3D11_TEXTURE2D_DESC *desc) +{ + ASSERT(desc); + + if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0) + { + // This will be done using ClearView methods. + return nullptr; + } + + size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc)); + if (mZeroMemory.size() < requiredSize) + { + mZeroMemory.resize(requiredSize); + mZeroMemory.fill(kDebugInitTextureDataValue); + } + + const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format); + + UINT subresourceCount = desc->MipLevels * desc->ArraySize; + if (mShadowInitData.size() < subresourceCount) + { + mShadowInitData.resize(subresourceCount); + } + + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex) + { + UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels); + D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex]; + + UINT levelWidth = std::max(desc->Width >> mipLevel, 1u); + UINT levelHeight = std::max(desc->Height >> mipLevel, 1u); + + data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes; + data->SysMemSlicePitch = data->SysMemPitch * levelHeight; + data->pSysMem = mZeroMemory.data(); + } + } + + return mShadowInitData.data(); +} + +template <> +const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>( + const D3D11_TEXTURE3D_DESC *desc) +{ + ASSERT(desc); + + if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0) + { + // This will be done using ClearView methods. + return nullptr; + } + + size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc)); + if (mZeroMemory.size() < requiredSize) + { + mZeroMemory.resize(requiredSize); + mZeroMemory.fill(kDebugInitTextureDataValue); + } + + const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format); + + UINT subresourceCount = desc->MipLevels; + if (mShadowInitData.size() < subresourceCount) + { + mShadowInitData.resize(subresourceCount); + } + + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels); + D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex]; + + UINT levelWidth = std::max(desc->Width >> mipLevel, 1u); + UINT levelHeight = std::max(desc->Height >> mipLevel, 1u); + + data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes; + data->SysMemSlicePitch = data->SysMemPitch * levelHeight; + data->pSysMem = mZeroMemory.data(); + } + + return mShadowInitData.data(); +} + +template <typename T> +GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc) +{ + // No-op. + return nullptr; +} + +void ResourceManager11::setAllocationsInitialized(bool initialize) +{ + mInitializeAllocations = initialize; +} + +#define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template \ +gl::Error \ + ResourceManager11::allocate(Renderer11 *, const DESCTYPE *, INITDATATYPE *, \ + Resource11<D3D11TYPE> *); + +ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP) +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h new file mode 100644 index 0000000000..0bdde9f8b6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h @@ -0,0 +1,366 @@ +// +// Copyright 2017 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. +// +// ResourceManager11: +// Centralized point of allocation for all D3D11 Resources. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ + +#include <array> +#include <memory> + +#include "common/MemoryBuffer.h" +#include "common/angleutils.h" +#include "common/debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/renderer_utils.h" + +namespace rx +{ +// These two methods are declared here to prevent circular includes. +namespace d3d11 +{ +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template <typename T> +HRESULT SetDebugName(angle::ComPtr<T> &resource, const char *name) +{ + return SetDebugName(resource.Get(), name); +} +} // namespace d3d11 + +class Renderer11; +class ResourceManager11; +template <typename T> +class SharedResource11; +class TextureHelper11; + +using InputElementArray = WrappedArray<D3D11_INPUT_ELEMENT_DESC>; +using ShaderData = WrappedArray<uint8_t>; + +// Format: ResourceType, D3D11 type, DESC type, init data type. +#define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \ + OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \ + OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \ + OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \ + const std::vector<D3D11_SO_DECLARATION_ENTRY>) \ + OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \ + OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \ + OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \ + OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \ + OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \ + OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void) + +#define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE, + +enum class ResourceType +{ + ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last +}; + +#undef ANGLE_RESOURCE_TYPE_LIST + +constexpr size_t ResourceTypeIndex(ResourceType resourceType) +{ + return static_cast<size_t>(resourceType); +} + +constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last); + +#define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME<ResourceType::RESTYPE> \ + { \ + using Value = D3D11TYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME<ResourceType::RESTYPE> \ + { \ + using Value = DESCTYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME<ResourceType::RESTYPE> \ + { \ + using Value = INITDATATYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \ + template <ResourceType Param> \ + struct NAME; \ + ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + \ +template<ResourceType Param> struct NAME \ + { \ + }; \ + \ +template<ResourceType Param> using Get##NAME = typename NAME<Param>::Value; + +ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11) +ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC) +ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA) + +#undef ANGLE_RESOURCE_TYPE_TO_D3D11 +#undef ANGLE_RESOURCE_TYPE_TO_DESC +#undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA +#undef ANGLE_RESOURCE_TYPE_TO_TYPE + +#define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \ + template <typename Param> \ + struct NAME; \ + ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + \ +template<typename Param> struct NAME \ + { \ + }; \ + \ +template<typename Param> constexpr ResourceType Get##NAME() \ + { \ + return NAME<Param>::Value; \ + } + +#define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME<D3D11TYPE> \ + { \ + static constexpr ResourceType Value = ResourceType::RESTYPE; \ + }; + +ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE) + +#undef ANGLE_D3D11_TO_RESOURCE_TYPE +#undef ANGLE_TYPE_TO_RESOURCE_TYPE + +template <typename T> +using GetDescFromD3D11 = GetDescType<ResourceTypeFromD3D11<T>::Value>; + +template <typename T> +using GetInitDataFromD3D11 = GetInitDataType<ResourceTypeFromD3D11<T>::Value>; + +template <typename T> +constexpr size_t ResourceTypeIndex() +{ + return static_cast<size_t>(GetResourceTypeFromD3D11<T>()); +} + +template <typename T> +struct TypedData +{ + TypedData() {} + ~TypedData(); + + T *object = nullptr; + ResourceManager11 *manager = nullptr; +}; + +// Smart pointer type. Wraps the resource and a factory for safe deletion. +template <typename T, template <class> class Pointer, typename DataT> +class Resource11Base : angle::NonCopyable +{ + public: + T *get() const { return mData->object; } + T *const *getPointer() const { return &mData->object; } + + void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); } + + void set(T *object) + { + ASSERT(!valid()); + mData->object = object; + } + + bool valid() const { return (mData->object != nullptr); } + + void reset() + { + if (valid()) + mData.reset(new DataT()); + } + + ResourceSerial getSerial() const + { + return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object)); + } + + protected: + friend class TextureHelper11; + + Resource11Base() : mData(new DataT()) {} + + Resource11Base(Resource11Base &&movedObj) : mData(new DataT()) + { + std::swap(mData, movedObj.mData); + } + + virtual ~Resource11Base() { mData.reset(); } + + Resource11Base &operator=(Resource11Base &&movedObj) + { + std::swap(mData, movedObj.mData); + return *this; + } + + Pointer<DataT> mData; +}; + +template <typename T> +using UniquePtr = typename std::unique_ptr<T, std::default_delete<T>>; + +template <typename ResourceT> +class Resource11 : public Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>> +{ + public: + Resource11() {} + Resource11(Resource11 &&other) + : Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>(std::move(other)) + { + } + Resource11 &operator=(Resource11 &&other) + { + std::swap(this->mData, other.mData); + return *this; + } + + private: + template <typename T> + friend class SharedResource11; + friend class ResourceManager11; + + Resource11(ResourceT *object, ResourceManager11 *manager) + { + this->mData->object = object; + this->mData->manager = manager; + } +}; + +template <typename T> +class SharedResource11 : public Resource11Base<T, std::shared_ptr, TypedData<T>> +{ + public: + SharedResource11() {} + SharedResource11(SharedResource11 &&movedObj) + : Resource11Base<T, std::shared_ptr, TypedData<T>>(std::move(movedObj)) + { + } + + SharedResource11 &operator=(SharedResource11 &&other) + { + std::swap(this->mData, other.mData); + return *this; + } + + SharedResource11 makeCopy() const + { + SharedResource11 copy; + copy.mData = this->mData; + return std::move(copy); + } + + private: + friend class ResourceManager11; + SharedResource11(Resource11<T> &&obj) : Resource11Base<T, std::shared_ptr, TypedData<T>>() + { + std::swap(this->mData->manager, obj.mData->manager); + + // Can't use std::swap because of ID3D11Resource. + auto temp = this->mData->object; + this->mData->object = obj.mData->object; + obj.mData->object = static_cast<T *>(temp); + } +}; + +class ResourceManager11 final : angle::NonCopyable +{ + public: + ResourceManager11(); + ~ResourceManager11(); + + template <typename T> + gl::Error allocate(Renderer11 *renderer, + const GetDescFromD3D11<T> *desc, + GetInitDataFromD3D11<T> *initData, + Resource11<T> *resourceOut); + + template <typename T> + gl::Error allocate(Renderer11 *renderer, + const GetDescFromD3D11<T> *desc, + GetInitDataFromD3D11<T> *initData, + SharedResource11<T> *sharedRes) + { + Resource11<T> res; + ANGLE_TRY(allocate(renderer, desc, initData, &res)); + *sharedRes = std::move(res); + return gl::NoError(); + } + + template <typename T> + void onRelease(T *resource) + { + onReleaseGeneric(GetResourceTypeFromD3D11<T>(), resource); + } + + void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource); + + void setAllocationsInitialized(bool initialize); + + private: + void incrResource(ResourceType resourceType, uint64_t memorySize); + void decrResource(ResourceType resourceType, uint64_t memorySize); + + template <typename T> + GetInitDataFromD3D11<T> *createInitDataIfNeeded(const GetDescFromD3D11<T> *desc); + + bool mInitializeAllocations; + + std::array<size_t, NumResourceTypes> mAllocatedResourceCounts; + std::array<uint64_t, NumResourceTypes> mAllocatedResourceDeviceMemory; + angle::MemoryBuffer mZeroMemory; + + std::vector<D3D11_SUBRESOURCE_DATA> mShadowInitData; +}; + +template <typename ResourceT> +TypedData<ResourceT>::~TypedData() +{ + if (object) + { + // We can have a nullptr factory when holding passed-in resources. + if (manager) + { + manager->onRelease(object); + } + object->Release(); + } +} + +#define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + using RESTYPE = Resource11<D3D11TYPE>; + +namespace d3d11 +{ +ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS) + +using SharedSRV = SharedResource11<ID3D11ShaderResourceView>; +} // namespace d3d11 + +#undef ANGLE_RESOURCE_TYPE_CLASS + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp index 4da51afe49..73a530add0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -13,86 +13,107 @@ namespace rx { -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::PixelShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(std::move(executable)), + mVertexExecutable(), + mGeometryExecutable(), + mStreamOutExecutable(), + mComputeExecutable() { - mPixelExecutable = executable; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = NULL; } -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::VertexShader &&executable, + d3d11::GeometryShader &&streamOut) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(std::move(executable)), + mGeometryExecutable(), + mStreamOutExecutable(std::move(streamOut)), + mComputeExecutable() { - mVertexExecutable = executable; - mPixelExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = streamOut; } -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::GeometryShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(), + mGeometryExecutable(std::move(executable)), + mStreamOutExecutable(), + mComputeExecutable() +{ +} + +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::ComputeShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(), + mGeometryExecutable(), + mStreamOutExecutable(), + mComputeExecutable(std::move(executable)) { - mGeometryExecutable = executable; - mVertexExecutable = NULL; - mPixelExecutable = NULL; - mStreamOutExecutable = NULL; } ShaderExecutable11::~ShaderExecutable11() { - SafeRelease(mVertexExecutable); - SafeRelease(mPixelExecutable); - SafeRelease(mGeometryExecutable); - SafeRelease(mStreamOutExecutable); } -ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +const d3d11::VertexShader &ShaderExecutable11::getVertexShader() const { return mVertexExecutable; } -ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +const d3d11::PixelShader &ShaderExecutable11::getPixelShader() const { return mPixelExecutable; } -ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +const d3d11::GeometryShader &ShaderExecutable11::getGeometryShader() const { return mGeometryExecutable; } -ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const +const d3d11::GeometryShader &ShaderExecutable11::getStreamOutShader() const { return mStreamOutExecutable; } -UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) - : UniformStorageD3D(initialSize), - mConstantBuffer(NULL) +const d3d11::ComputeShader &ShaderExecutable11::getComputeShader() const { - ID3D11Device *d3d11Device = renderer->getDevice(); + return mComputeExecutable; +} - 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); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - } +UniformStorage11::UniformStorage11(size_t initialSize) + : UniformStorageD3D(initialSize), mConstantBuffer() +{ } UniformStorage11::~UniformStorage11() { - SafeRelease(mConstantBuffer); } +gl::Error UniformStorage11::getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut) +{ + if (size() > 0 && !mConstantBuffer.valid()) + { + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = static_cast<unsigned int>(size()); + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + ANGLE_TRY(renderer->allocateResource(desc, &mConstantBuffer)); + } + + *bufferOut = &mConstantBuffer; + return gl::NoError(); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h index 379f39fe53..3f417578a3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -11,6 +11,7 @@ #define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -20,36 +21,42 @@ 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; + ShaderExecutable11(const void *function, size_t length, d3d11::PixelShader &&executable); + ShaderExecutable11(const void *function, + size_t length, + d3d11::VertexShader &&executable, + d3d11::GeometryShader &&streamOut); + ShaderExecutable11(const void *function, size_t length, d3d11::GeometryShader &&executable); + ShaderExecutable11(const void *function, size_t length, d3d11::ComputeShader &&executable); + + ~ShaderExecutable11() override; + + const d3d11::PixelShader &getPixelShader() const; + const d3d11::VertexShader &getVertexShader() const; + const d3d11::GeometryShader &getGeometryShader() const; + const d3d11::GeometryShader &getStreamOutShader() const; + const d3d11::ComputeShader &getComputeShader() const; private: - ID3D11PixelShader *mPixelExecutable; - ID3D11VertexShader *mVertexExecutable; - ID3D11GeometryShader *mGeometryExecutable; - ID3D11GeometryShader *mStreamOutExecutable; + d3d11::PixelShader mPixelExecutable; + d3d11::VertexShader mVertexExecutable; + d3d11::GeometryShader mGeometryExecutable; + d3d11::GeometryShader mStreamOutExecutable; + d3d11::ComputeShader mComputeExecutable; }; class UniformStorage11 : public UniformStorageD3D { public: - UniformStorage11(Renderer11 *renderer, size_t initialSize); - virtual ~UniformStorage11(); + UniformStorage11(size_t initialSize); + ~UniformStorage11() override; - ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + gl::Error getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut); private: - ID3D11Buffer *mConstantBuffer; + d3d11::Buffer mConstantBuffer; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp index aa34fd4de8..e9902d3f14 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -8,11 +8,22 @@ #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" -#include "common/BitSetIterator.h" +#include "common/bitset_utils.h" #include "common/utilities.h" +#include "libANGLE/Context.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Context11.h" #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" namespace rx { @@ -22,15 +33,16 @@ namespace bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) { unsigned mipLevel = index.mipIndex; - unsigned layerIndex = index.layerIndex; + GLint layerIndex = index.layerIndex; GLenum type = index.type; switch (desc.ViewDimension) { case D3D11_SRV_DIMENSION_TEXTURE2D: { - unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; - maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip; + 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; @@ -42,22 +54,25 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: { - unsigned maxSrvMip = + bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max()); + unsigned int maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; - maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; + 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 <= layerIndex && layerIndex < maxSlice; + desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) && + static_cast<UINT>(layerIndex) < maxSlice; } case D3D11_SRV_DIMENSION_TEXTURECUBE: { - unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; - maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + 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; @@ -65,8 +80,9 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR case D3D11_SRV_DIMENSION_TEXTURE3D: { - unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; - maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; + 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; @@ -82,15 +98,97 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR // Does *not* increment the resource ref count!! ID3D11Resource *GetViewResource(ID3D11View *view) { - ID3D11Resource *resource = NULL; + ID3D11Resource *resource = nullptr; ASSERT(view); view->GetResource(&resource); resource->Release(); return resource; } +int GetWrapBits(GLenum wrap) +{ + switch (wrap) + { + case GL_CLAMP_TO_EDGE: + return 0x1; + case GL_REPEAT: + return 0x2; + case GL_MIRRORED_REPEAT: + return 0x3; + default: + UNREACHABLE(); + return 0; + } +} + +Optional<size_t> FindFirstNonInstanced( + const std::vector<const TranslatedAttribute *> ¤tAttributes) +{ + for (size_t index = 0; index < currentAttributes.size(); ++index) + { + if (currentAttributes[index]->divisor == 0) + { + return Optional<size_t>(index); + } + } + + return Optional<size_t>::Invalid(); +} + +void SortAttributesByLayout(const gl::Program *program, + const std::vector<TranslatedAttribute> &vertexArrayAttribs, + const std::vector<TranslatedAttribute> ¤tValueAttribs, + AttribIndexArray *sortedD3DSemanticsOut, + std::vector<const TranslatedAttribute *> *sortedAttributesOut) +{ + sortedAttributesOut->clear(); + + const auto &locationToSemantic = + GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics(); + + for (auto locationIndex : program->getActiveAttribLocationsMask()) + { + int d3dSemantic = locationToSemantic[locationIndex]; + if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic)) + { + sortedAttributesOut->resize(d3dSemantic + 1); + } + + (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic; + + const auto *arrayAttrib = &vertexArrayAttribs[locationIndex]; + if (arrayAttrib->attribute && arrayAttrib->attribute->enabled) + { + (*sortedAttributesOut)[d3dSemantic] = arrayAttrib; + } + else + { + ASSERT(currentValueAttribs[locationIndex].attribute); + (*sortedAttributesOut)[d3dSemantic] = ¤tValueAttribs[locationIndex]; + } + } +} + +void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext, + UniformStorage11 *storage, + const d3d11::Buffer *buffer) +{ + deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0, + 0); +} + } // anonymous namespace +// StateManager11::SRVCache Implementation. + +StateManager11::SRVCache::SRVCache() : mHighestUsedSRV(0) +{ +} + +StateManager11::SRVCache::~SRVCache() +{ +} + void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) { ASSERT(resourceIndex < mCurrentSRVs.size()); @@ -128,27 +226,348 @@ void StateManager11::SRVCache::clear() mHighestUsedSRV = 0; } +// ShaderConstants11 implementation + +ShaderConstants11::ShaderConstants11() + : mVertexDirty(true), + mPixelDirty(true), + mComputeDirty(true), + mSamplerMetadataVSDirty(true), + mSamplerMetadataPSDirty(true), + mSamplerMetadataCSDirty(true) +{ +} + +ShaderConstants11::~ShaderConstants11() +{ +} + +void ShaderConstants11::init(const gl::Caps &caps) +{ + mSamplerMetadataVS.resize(caps.maxVertexTextureImageUnits); + mSamplerMetadataPS.resize(caps.maxTextureImageUnits); + mSamplerMetadataCS.resize(caps.maxComputeTextureImageUnits); +} + +size_t ShaderConstants11::getRequiredBufferSize(gl::SamplerType samplerType) const +{ + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + return sizeof(Vertex) + mSamplerMetadataVS.size() * sizeof(SamplerMetadata); + case gl::SAMPLER_PIXEL: + return sizeof(Pixel) + mSamplerMetadataPS.size() * sizeof(SamplerMetadata); + case gl::SAMPLER_COMPUTE: + return sizeof(Compute) + mSamplerMetadataCS.size() * sizeof(SamplerMetadata); + default: + UNREACHABLE(); + return 0; + } +} + +void ShaderConstants11::markDirty() +{ + mVertexDirty = true; + mPixelDirty = true; + mComputeDirty = true; + mSamplerMetadataVSDirty = true; + mSamplerMetadataPSDirty = true; + mSamplerMetadataCSDirty = true; +} + +bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture) +{ + bool dirty = false; + unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel(); + GLenum sizedFormat = + texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat; + if (data->baseLevel != static_cast<int>(baseLevel)) + { + data->baseLevel = static_cast<int>(baseLevel); + dirty = true; + } + + // Some metadata is needed only for integer textures. We avoid updating the constant buffer + // unnecessarily by changing the data only in case the texture is an integer texture and + // the values have changed. + bool needIntegerTextureMetadata = false; + // internalFormatBits == 0 means a 32-bit texture in the case of integer textures. + int internalFormatBits = 0; + switch (sizedFormat) + { + case GL_RGBA32I: + case GL_RGBA32UI: + case GL_RGB32I: + case GL_RGB32UI: + case GL_RG32I: + case GL_RG32UI: + case GL_R32I: + case GL_R32UI: + needIntegerTextureMetadata = true; + break; + case GL_RGBA16I: + case GL_RGBA16UI: + case GL_RGB16I: + case GL_RGB16UI: + case GL_RG16I: + case GL_RG16UI: + case GL_R16I: + case GL_R16UI: + needIntegerTextureMetadata = true; + internalFormatBits = 16; + break; + case GL_RGBA8I: + case GL_RGBA8UI: + case GL_RGB8I: + case GL_RGB8UI: + case GL_RG8I: + case GL_RG8UI: + case GL_R8I: + case GL_R8UI: + needIntegerTextureMetadata = true; + internalFormatBits = 8; + break; + case GL_RGB10_A2UI: + needIntegerTextureMetadata = true; + internalFormatBits = 10; + break; + default: + break; + } + if (needIntegerTextureMetadata) + { + if (data->internalFormatBits != internalFormatBits) + { + data->internalFormatBits = internalFormatBits; + dirty = true; + } + // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer + // vector. + GLenum wrapS = texture.getWrapS(); + GLenum wrapT = texture.getWrapT(); + GLenum wrapR = texture.getWrapR(); + int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4); + if (data->wrapModes != wrapModes) + { + data->wrapModes = wrapModes; + dirty = true; + } + } + + return dirty; +} + +void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + mCompute.numWorkGroups[0] = numGroupsX; + mCompute.numWorkGroups[1] = numGroupsY; + mCompute.numWorkGroups[2] = numGroupsZ; + mComputeDirty = true; +} + +void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index) +{ + mVertex.multiviewWriteToViewportIndex = index; + mVertexDirty = true; + mPixel.multiviewWriteToViewportIndex = index; + mPixelDirty = true; +} + +void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport, + const D3D11_VIEWPORT &dxViewport, + bool is9_3, + bool presentPathFast) +{ + mVertexDirty = true; + mPixelDirty = true; + + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders + // using viewAdjust (like the D3D9 renderer). + if (is9_3) + { + mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) + + 2 * (glViewport.x - dxViewport.TopLeftX)) / + dxViewport.Width; + mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) + + 2 * (glViewport.y - dxViewport.TopLeftY)) / + dxViewport.Height; + mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width; + mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height; + } + + mPixel.viewCoords[0] = glViewport.width * 0.5f; + mPixel.viewCoords[1] = glViewport.height * 0.5f; + mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f); + mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f); + + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertex.viewCoords[0] = mPixel.viewCoords[0]; + mVertex.viewCoords[1] = mPixel.viewCoords[1]; + mVertex.viewCoords[2] = mPixel.viewCoords[2]; + mVertex.viewCoords[3] = mPixel.viewCoords[3]; + + const float zNear = dxViewport.MinDepth; + const float zFar = dxViewport.MaxDepth; + + mPixel.depthFront[0] = (zFar - zNear) * 0.5f; + mPixel.depthFront[1] = (zNear + zFar) * 0.5f; + + mVertex.depthRange[0] = zNear; + mVertex.depthRange[1] = zFar; + mVertex.depthRange[2] = zFar - zNear; + + mPixel.depthRange[0] = zNear; + mPixel.depthRange[1] = zFar; + mPixel.depthRange[2] = zFar - zNear; + + mPixel.viewScale[0] = 1.0f; + mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f; + // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw + // framebuffer's layout is changed. + + mVertex.viewScale[0] = mPixel.viewScale[0]; + mVertex.viewScale[1] = mPixel.viewScale[1]; +} + +void ShaderConstants11::onSamplerChange(gl::SamplerType samplerType, + unsigned int samplerIndex, + const gl::Texture &texture) +{ + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + if (updateSamplerMetadata(&mSamplerMetadataVS[samplerIndex], texture)) + { + mSamplerMetadataVSDirty = true; + } + break; + case gl::SAMPLER_PIXEL: + if (updateSamplerMetadata(&mSamplerMetadataPS[samplerIndex], texture)) + { + mSamplerMetadataPSDirty = true; + } + break; + case gl::SAMPLER_COMPUTE: + if (updateSamplerMetadata(&mSamplerMetadataCS[samplerIndex], texture)) + { + mSamplerMetadataCSDirty = true; + } + break; + default: + UNREACHABLE(); + break; + } +} + +gl::Error ShaderConstants11::updateBuffer(ID3D11DeviceContext *deviceContext, + gl::SamplerType samplerType, + const ProgramD3D &programD3D, + const d3d11::Buffer &driverConstantBuffer) +{ + bool dirty = false; + size_t dataSize = 0; + const uint8_t *data = nullptr; + const uint8_t *samplerData = nullptr; + + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + dirty = mVertexDirty || mSamplerMetadataVSDirty; + dataSize = sizeof(Vertex); + data = reinterpret_cast<const uint8_t *>(&mVertex); + samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataVS.data()); + mVertexDirty = false; + mSamplerMetadataVSDirty = false; + break; + case gl::SAMPLER_PIXEL: + dirty = mPixelDirty || mSamplerMetadataPSDirty; + dataSize = sizeof(Pixel); + data = reinterpret_cast<const uint8_t *>(&mPixel); + samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataPS.data()); + mPixelDirty = false; + mSamplerMetadataPSDirty = false; + break; + case gl::SAMPLER_COMPUTE: + dirty = mComputeDirty || mSamplerMetadataCSDirty; + dataSize = sizeof(Compute); + data = reinterpret_cast<const uint8_t *>(&mCompute); + samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataCS.data()); + mComputeDirty = false; + mSamplerMetadataCSDirty = false; + break; + default: + UNREACHABLE(); + break; + } + + ASSERT(driverConstantBuffer.valid()); + + if (!dirty) + { + return gl::NoError(); + } + + // Previous buffer contents are discarded, so we need to refresh the whole buffer. + D3D11_MAPPED_SUBRESOURCE mapping = {0}; + HRESULT result = + deviceContext->Map(driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping); + + if (FAILED(result)) + { + return gl::OutOfMemory() << "Internal error mapping constant buffer: " << gl::FmtHR(result); + } + + size_t samplerDataBytes = sizeof(SamplerMetadata) * programD3D.getUsedSamplerRange(samplerType); + + memcpy(mapping.pData, data, dataSize); + memcpy(reinterpret_cast<uint8_t *>(mapping.pData) + dataSize, samplerData, samplerDataBytes); + + deviceContext->Unmap(driverConstantBuffer.get(), 0); + + return gl::NoError(); +} + +static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT, + GL_COMMANDS_COMPLETED_CHROMIUM}; + StateManager11::StateManager11(Renderer11 *renderer) : mRenderer(renderer), - mBlendStateIsDirty(false), + mInternalDirtyBits(), 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(true), mCurPresentPathFastEnabled(false), mCurPresentPathFastColorBufferHeight(0), - mAppliedDSV(angle::DirtyPointer) + mDirtyCurrentValueAttribs(), + mCurrentValueAttribs(), + mCurrentInputLayout(), + mInputLayoutIsDirty(false), + mVertexAttribsNeedTranslation(false), + mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0), + mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED), + mDirtySwizzles(false), + mAppliedIB(nullptr), + mAppliedIBFormat(DXGI_FORMAT_UNKNOWN), + mAppliedIBOffset(0), + mIndexBufferIsDirty(false), + mVertexDataManager(renderer), + mIndexDataManager(renderer), + mIsMultiviewEnabled(false), + mEmptySerial(mRenderer->generateSerial()), + mIsTransformFeedbackCurrentlyActiveUnpaused(false) { mCurBlendState.blend = false; mCurBlendState.sourceBlendRGB = GL_ONE; @@ -182,64 +601,127 @@ StateManager11::StateManager11(Renderer11 *renderer) mCurRasterState.rasterizerDiscard = false; mCurRasterState.cullFace = false; - mCurRasterState.cullMode = GL_BACK; + mCurRasterState.cullMode = gl::CullFaceMode::Back; mCurRasterState.frontFace = GL_CCW; mCurRasterState.polygonOffsetFill = false; mCurRasterState.polygonOffsetFactor = 0.0f; mCurRasterState.polygonOffsetUnits = 0.0f; mCurRasterState.pointDrawMode = false; mCurRasterState.multiSample = false; + + // Start with all internal dirty bits set. + mInternalDirtyBits.set(); + + // Initially all current value attributes must be updated on first use. + mDirtyCurrentValueAttribs.set(); + + mCurrentVertexBuffers.fill(nullptr); + mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max()); + mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max()); } StateManager11::~StateManager11() { } -void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, - unsigned int stencilSize) +template <typename SRVType> +void StateManager11::setShaderResourceInternal(gl::SamplerType shaderType, + UINT resourceSlot, + const SRVType *srv) { - if (!depthStencilInitialized || stencilSize != mCurStencilSize) + 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)) { - mCurStencilSize = stencilSize; - mDepthStencilStateIsDirty = true; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr; + if (shaderType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr); + } + else + { + deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr); + } + + currentSRVs.update(resourceSlot, srvPtr); } } -void StateManager11::setViewportBounds(const int width, const int height) +void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) { - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && - (mViewportBounds.width != width || mViewportBounds.height != height)) + if (!depthStencilInitialized || stencilSize != mCurStencilSize) { - mViewportBounds = gl::Extents(width, height, 1); - mViewportStateIsDirty = true; + mCurStencilSize = stencilSize; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } } -void StateManager11::updatePresentPath(bool presentPathFastActive, - const gl::FramebufferAttachment *framebufferAttachment) +void StateManager11::checkPresentPath(const gl::Context *context) { - const int colorBufferHeight = - framebufferAttachment ? framebufferAttachment->getSize().height : 0; + if (!mRenderer->presentPathFastEnabled()) + return; + + const auto *framebuffer = context->getGLState().getDrawFramebuffer(); + const auto *firstColorAttachment = framebuffer->getFirstColorbuffer(); + const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment); + + const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0; if ((mCurPresentPathFastEnabled != presentPathFastActive) || (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight))) { mCurPresentPathFastEnabled = presentPathFastActive; mCurPresentPathFastColorBufferHeight = colorBufferHeight; - 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 + + // Scissor rect may need to be vertically inverted + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); + + // Cull Mode may need to be inverted + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Viewport may need to be vertically inverted + invalidateViewport(context); } } -void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +gl::Error StateManager11::updateStateForCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); + + // TODO(jmadill): Use dirty bits. + const auto &glState = context->getGLState(); + auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + programD3D->updateSamplerMapping(); + + // TODO(jmadill): Use dirty bits. + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_COMPUTE)); + + // TODO(jmadill): More complete implementation. + ANGLE_TRY(syncTextures(context)); + + // TODO(Xinghua): applyUniformBuffers for compute shader. + + return gl::NoError(); +} + +void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) { if (!dirtyBits.any()) { return; } - for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits)) + const auto &state = context->getGLState(); + + for (auto dirtyBit : dirtyBits) { switch (dirtyBit) { @@ -249,7 +731,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } @@ -261,27 +743,27 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } case gl::State::DIRTY_BIT_BLEND_ENABLED: if (state.getBlendState().blend != mCurBlendState.blend) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: if (state.getBlendState().sampleAlphaToCoverage != mCurBlendState.sampleAlphaToCoverage) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_DITHER_ENABLED: if (state.getBlendState().dither != mCurBlendState.dither) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_COLOR_MASK: @@ -292,38 +774,38 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } case gl::State::DIRTY_BIT_BLEND_COLOR: if (state.getBlendColor() != mCurBlendColor) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_MASK: if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_FUNC: if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: @@ -333,7 +815,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilMask != mCurDepthStencilState.stencilMask || state.getStencilRef() != mCurStencilRef) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -344,7 +826,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || state.getStencilBackRef() != mCurStencilBackRef) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -352,14 +834,14 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (state.getDepthStencilState().stencilWritemask != mCurDepthStencilState.stencilWritemask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: if (state.getDepthStencilState().stencilBackWritemask != mCurDepthStencilState.stencilBackWritemask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: @@ -370,7 +852,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit mCurDepthStencilState.stencilPassDepthFail || depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -383,33 +865,33 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilBackPassDepthPass != mCurDepthStencilState.stencilBackPassDepthPass) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_CULL_FACE: if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_FRONT_FACE: if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: if (state.getRasterizerState().polygonOffsetFill != mCurRasterState.polygonOffsetFill) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: @@ -418,7 +900,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; } @@ -426,58 +908,150 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (state.getRasterizerState().rasterizerDiscard != mCurRasterState.rasterizerDiscard) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Enabling/disabling rasterizer discard affects the pixel shader. + invalidateShaders(); } break; case gl::State::DIRTY_BIT_SCISSOR: if (state.getScissor() != mCurScissorRect) { - mScissorStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); } break; case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: if (state.isScissorTestEnabled() != mCurScissorEnabled) { - mScissorStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); // Rasterizer state update needs mCurScissorsEnabled and updates when it changes - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_RANGE: if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) { - mViewportStateIsDirty = true; + invalidateViewport(context); } break; case gl::State::DIRTY_BIT_VIEWPORT: if (state.getViewport() != mCurViewport) { - mViewportStateIsDirty = true; + invalidateViewport(context); + } + break; + case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: + invalidateRenderTarget(); + if (mIsMultiviewEnabled) + { + handleMultiviewDrawFramebufferChange(context); } break; + case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: + invalidateVertexBuffer(); + // Force invalidate the current value attributes, since the VertexArray11 keeps an + // internal cache of TranslatedAttributes, and they CurrentValue attributes are + // owned by the StateManager11/Context. + mDirtyCurrentValueAttribs.set(); + // Invalidate the cached index buffer. + mIndexBufferIsDirty = true; + break; + case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: + invalidateTexturesAndSamplers(); + break; + case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: + invalidateTexturesAndSamplers(); + break; + case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: + { + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); + invalidateVertexBuffer(); + invalidateRenderTarget(); + invalidateTexturesAndSamplers(); + invalidateProgramUniforms(); + invalidateProgramUniformBuffers(); + gl::VertexArray *vao = state.getVertexArray(); + if (mIsMultiviewEnabled && vao != nullptr) + { + // If ANGLE_multiview is enabled, the attribute divisor has to be updated for + // each binding. + VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); + const gl::Program *program = state.getProgram(); + int numViews = 1; + if (program != nullptr && program->usesMultiview()) + { + numViews = program->getNumViews(); + } + vao11->markAllAttributeDivisorsForAdjustment(numViews); + } + break; + } + case gl::State::DIRTY_BIT_CURRENT_VALUES: + { + for (auto attribIndex : state.getAndResetDirtyCurrentValues()) + { + invalidateCurrentValueAttrib(attribIndex); + } + } default: break; } } + + // TODO(jmadill): Input layout and vertex buffer state. } -gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, - const gl::BlendState &blendState, - const gl::ColorF &blendColor, - unsigned int sampleMask) +void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context) { - if (!mBlendStateIsDirty && sampleMask == mCurSampleMask) + const auto &glState = context->getGLState(); + const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); + ASSERT(drawFramebuffer != nullptr); + + // Update viewport offsets. + const std::vector<gl::Offset> *attachmentViewportOffsets = + drawFramebuffer->getViewportOffsets(); + const std::vector<gl::Offset> &viewportOffsets = + attachmentViewportOffsets != nullptr + ? *attachmentViewportOffsets + : gl::FramebufferAttachment::GetDefaultViewportOffsetVector(); + if (mViewportOffsets != viewportOffsets) { - return gl::Error(GL_NO_ERROR); - } + mViewportOffsets = viewportOffsets; - ID3D11BlendState *dxBlendState = nullptr; - gl::Error error = - mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState); - if (error.isError()) + // Because new viewport offsets are to be applied, we have to mark the internal viewport and + // scissor state as dirty. + invalidateViewport(context); + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); + } + switch (drawFramebuffer->getMultiviewLayout()) { - return error; + case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE: + mShaderConstants.setMultiviewWriteToViewportIndex(1.0f); + break; + case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE: + // Because the base view index is applied as an offset to the 2D texture array when the + // RTV is created, we just have to pass a boolean to select which code path is to be + // used. + mShaderConstants.setMultiviewWriteToViewportIndex(0.0f); + break; + default: + // There is no need to update the value in the constant buffer if the active framebuffer + // object does not have a multiview layout. + break; } +} + +gl::Error StateManager11::syncBlendState(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + const d3d11::BlendState *dxBlendState = nullptr; + const d3d11::BlendStateKey &key = + RenderStateCache::GetBlendStateKey(context, framebuffer, blendState); + + ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState)); ASSERT(dxBlendState != nullptr); @@ -500,62 +1074,53 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, blendColors[3] = blendColor.alpha; } - mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask); + mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask); mCurBlendState = blendState; mCurBlendColor = blendColor; mCurSampleMask = sampleMask; - mBlendStateIsDirty = false; - - return error; + return gl::NoError(); } -gl::Error StateManager11::setDepthStencilState(const gl::State &glState) +gl::Error StateManager11::syncDepthStencilState(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()); + mCurDepthStencilState = glState.getDepthStencilState(); + mCurStencilRef = glState.getStencilRef(); + mCurStencilBackRef = glState.getStencilBackRef(); - // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. - if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && - disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && - disableStencil == mCurDisableStencil.value()) + // get the maximum size of the stencil ref + unsigned int maxStencil = 0; + if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0) { - return gl::Error(GL_NO_ERROR); + maxStencil = (1 << mCurStencilSize) - 1; } + ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) == + (mCurDepthStencilState.stencilBackWritemask & maxStencil)); + ASSERT(mCurStencilRef == mCurStencilBackRef); + ASSERT((mCurDepthStencilState.stencilMask & maxStencil) == + (mCurDepthStencilState.stencilBackMask & maxStencil)); - const auto &depthStencilState = glState.getDepthStencilState(); - int stencilRef = glState.getStencilRef(); - int stencilBackRef = glState.getStencilBackRef(); + gl::DepthStencilState modifiedGLState = glState.getDepthStencilState(); - // get the maximum size of the stencil ref - unsigned int maxStencil = 0; - if (depthStencilState.stencilTest && mCurStencilSize > 0) + ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid()); + + if (mCurDisableDepth.value()) { - maxStencil = (1 << mCurStencilSize) - 1; + modifiedGLState.depthTest = false; + modifiedGLState.depthMask = false; } - ASSERT((depthStencilState.stencilWritemask & maxStencil) == - (depthStencilState.stencilBackWritemask & maxStencil)); - ASSERT(stencilRef == stencilBackRef); - ASSERT((depthStencilState.stencilMask & maxStencil) == - (depthStencilState.stencilBackMask & maxStencil)); - ID3D11DepthStencilState *dxDepthStencilState = NULL; - gl::Error error = mRenderer->getStateCache().getDepthStencilState( - depthStencilState, disableDepth, disableStencil, &dxDepthStencilState); - if (error.isError()) + if (mCurDisableStencil.value()) { - return error; + modifiedGLState.stencilWritemask = 0; + modifiedGLState.stencilBackWritemask = 0; + modifiedGLState.stencilTest = false; } - ASSERT(dxDepthStencilState); + const d3d11::DepthStencilState *d3dState = nullptr; + ANGLE_TRY(mRenderer->getDepthStencilState(modifiedGLState, &d3dState)); + ASSERT(d3dState); // Max D3D11 stencil reference value is 0xFF, // corresponding to the max 8 bits in a stencil buffer @@ -565,30 +1130,21 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState) "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); - UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); + UINT dxStencilRef = std::min<UINT>(mCurStencilRef, 0xFFu); - mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef); - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurDisableDepth = disableDepth; - mCurDisableStencil = disableStencil; - - mDepthStencilStateIsDirty = false; - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error StateManager11::syncRasterizerState(const gl::Context *context, bool pointDrawMode) { - if (!mRasterizerStateIsDirty) - { - return gl::Error(GL_NO_ERROR); - } + // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState. + gl::RasterizerState rasterState = context->getGLState().getRasterizerState(); + rasterState.pointDrawMode = pointDrawMode; + rasterState.multiSample = mCurRasterState.multiSample; ID3D11RasterizerState *dxRasterState = nullptr; - gl::Error error(GL_NO_ERROR); if (mCurPresentPathFastEnabled) { @@ -607,33 +1163,23 @@ gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterSt modifiedRasterState.frontFace = GL_CCW; } - error = mRenderer->getStateCache().getRasterizerState(modifiedRasterState, - mCurScissorEnabled, &dxRasterState); + ANGLE_TRY( + mRenderer->getRasterizerState(modifiedRasterState, mCurScissorEnabled, &dxRasterState)); } else { - error = mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled, - &dxRasterState); - } - - if (error.isError()) - { - return error; + ANGLE_TRY(mRenderer->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState)); } mRenderer->getDeviceContext()->RSSetState(dxRasterState); - mCurRasterState = rasterState; - mRasterizerStateIsDirty = false; + mCurRasterState = rasterState; - return error; + return gl::NoError(); } -void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled) { - if (!mScissorStateIsDirty) - return; - int modifiedScissorY = scissor.y; if (mCurPresentPathFastEnabled) { @@ -642,37 +1188,41 @@ void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enab 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); + std::array<D3D11_RECT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> rectangles; + const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size()); + for (UINT i = 0u; i < numRectangles; ++i) + { + D3D11_RECT &rect = rectangles[i]; + int x = scissor.x + mViewportOffsets[i].x; + int y = modifiedScissorY + mViewportOffsets[i].y; + rect.left = std::max(0, x); + rect.top = std::max(0, y); + rect.right = x + std::max(0, scissor.width); + rect.bottom = y + std::max(0, scissor.height); + } + mRenderer->getDeviceContext()->RSSetScissorRects(numRectangles, rectangles.data()); } mCurScissorRect = scissor; mCurScissorEnabled = enabled; - mScissorStateIsDirty = false; } -void StateManager11::setViewport(const gl::Caps *caps, - const gl::Rectangle &viewport, - float zNear, - float zFar) +void StateManager11::syncViewport(const gl::Context *context) { - 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); + const auto &glState = context->getGLState(); + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + float actualZNear = gl::clamp01(glState.getNearPlane()); + float actualZFar = gl::clamp01(glState.getFarPlane()); + + const auto &caps = context->getCaps(); + int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth); + int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight); int dxMinViewportBoundsX = -dxMaxViewportBoundsX; int dxMinViewportBoundsY = -dxMaxViewportBoundsY; - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3; + + if (is9_3) { // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width); @@ -681,173 +1231,295 @@ void StateManager11::setViewport(const gl::Caps *caps, 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); + const auto &viewport = glState.getViewport(); + std::array<D3D11_VIEWPORT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> dxViewports; + const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size()); - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); + int dxViewportTopLeftX = 0; + int dxViewportTopLeftY = 0; + int dxViewportWidth = 0; + int dxViewportHeight = 0; - 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 + for (UINT i = 0u; i < numRectangles; ++i) { - dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); - } + dxViewportTopLeftX = gl::clamp(viewport.x + mViewportOffsets[i].x, dxMinViewportBoundsX, + dxMaxViewportBoundsX); + dxViewportTopLeftY = gl::clamp(viewport.y + mViewportOffsets[i].y, dxMinViewportBoundsY, + dxMaxViewportBoundsY); + dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT &dxViewport = dxViewports[i]; + dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); + if (mCurPresentPathFastEnabled) + { + // When present path fast is active and we're rendering to framebuffer 0, we must invert + // the viewport in Y-axis. + // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave + // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the + // unaltered dxViewportTopLeftY value. + dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight - + dxViewportTopLeftY - dxViewportHeight); + } + else + { + dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); + } - dxViewport.Width = static_cast<float>(dxViewportWidth); - dxViewport.Height = static_cast<float>(dxViewportHeight); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; + // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering + // will be limited to a rectangle having a lower left of (0, 0) and an upper right of + // (width, height), where width and height are the framebuffer object's default width + // and height." See http://anglebug.com/1594 + // If the Framebuffer has no color attachment and the default width or height is smaller + // than the current viewport, use the smaller of the two sizes. + // If framebuffer default width or height is 0, the params should not set. + if (!framebuffer->getFirstNonNullAttachment() && + (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight())) + { + dxViewport.Width = + static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth())); + dxViewport.Height = + static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight())); + } + else + { + dxViewport.Width = static_cast<float>(dxViewportWidth); + dxViewport.Height = static_cast<float>(dxViewportHeight); + } + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + } - mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport); + mRenderer->getDeviceContext()->RSSetViewports(numRectangles, dxViewports.data()); 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). + const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX), + static_cast<FLOAT>(dxViewportTopLeftY), + static_cast<FLOAT>(dxViewportWidth), + static_cast<FLOAT>(dxViewportHeight), + actualZNear, + actualZFar}; + mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled); +} + +void StateManager11::invalidateRenderTarget() +{ + mRenderTargetIsDirty = true; +} + +void StateManager11::processFramebufferInvalidation(const gl::Context *context) +{ + if (!mRenderTargetIsDirty) + { + return; + } + + ASSERT(context); + + mRenderTargetIsDirty = false; + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); + + // The pixel shader is dependent on the output layout. + invalidateShaders(); + + // The D3D11 blend state is heavily dependent on the current render target. + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); + + gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer(); + ASSERT(fbo); + + // Disable the depth test/depth write if we are using a stencil-only attachment. + // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read + // nor write to the unused depth part of this emulated texture. + bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil()); + + // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. + bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil()); + + if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() || + !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value()) + { + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); + mCurDisableDepth = disableDepth; + mCurDisableStencil = disableStencil; + } + + bool multiSample = (fbo->getCachedSamples(context) != 0); + if (multiSample != mCurRasterState.multiSample) + { + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + mCurRasterState.multiSample = multiSample; + } + + checkPresentPath(context); + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { - 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; + const auto *firstAttachment = fbo->getFirstNonNullAttachment(); + if (firstAttachment) + { + const auto &size = firstAttachment->getSize(); + if (mViewportBounds.width != size.width || mViewportBounds.height != size.height) + { + mViewportBounds = gl::Extents(size.width, size.height, 1); + invalidateViewport(context); + } + } } +} - 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); +void StateManager11::invalidateBoundViews() +{ + mCurVertexSRVs.clear(); + mCurPixelSRVs.clear(); - // 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]; + invalidateRenderTarget(); +} - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; +void StateManager11::invalidateVertexBuffer() +{ + unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes, + gl::MAX_VERTEX_ATTRIBS); + mDirtyVertexBufferRange = gl::RangeUI(0, limit); + mInputLayoutIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); + invalidateVertexAttributeTranslation(); +} - mVertexConstants.depthRange[0] = actualZNear; - mVertexConstants.depthRange[1] = actualZFar; - mVertexConstants.depthRange[2] = actualZFar - actualZNear; +void StateManager11::invalidateViewport(const gl::Context *context) +{ + mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); - mPixelConstants.depthRange[0] = actualZNear; - mPixelConstants.depthRange[1] = actualZFar; - mPixelConstants.depthRange[2] = actualZFar - actualZNear; + // Viewport affects the driver constants. + invalidateDriverUniforms(); +} - mPixelConstants.viewScale[0] = 1.0f; - mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f; - mPixelConstants.viewScale[2] = 1.0f; - mPixelConstants.viewScale[3] = 1.0f; +void StateManager11::invalidateTexturesAndSamplers() +{ + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + invalidateSwizzles(); - mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0]; - mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1]; - mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2]; - mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3]; + // Texture state affects the driver uniforms (base level, etc). + invalidateDriverUniforms(); +} - mViewportStateIsDirty = false; +void StateManager11::invalidateSwizzles() +{ + mDirtySwizzles = true; } -void StateManager11::invalidateRenderTarget() +void StateManager11::invalidateProgramUniforms() +{ + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); +} + +void StateManager11::invalidateDriverUniforms() +{ + mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); +} + +void StateManager11::invalidateProgramUniformBuffers() +{ + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); +} + +void StateManager11::invalidateConstantBuffer(unsigned int slot) { - for (auto &appliedRTV : mAppliedRTVs) + if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER) { - appliedRTV = angle::DirtyPointer; + invalidateDriverUniforms(); + } + else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK) + { + invalidateProgramUniforms(); + } + else + { + invalidateProgramUniformBuffers(); } - mAppliedDSV = angle::DirtyPointer; } -void StateManager11::invalidateEverything() +void StateManager11::invalidateShaders() { - mBlendStateIsDirty = true; - mDepthStencilStateIsDirty = true; - mRasterizerStateIsDirty = true; - mScissorStateIsDirty = true; - mViewportStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); +} - // We reset the current SRV data because it might not be in sync with D3D's state - // anymore. For example when a currently used SRV is used as an RTV, D3D silently - // remove it from its state. - mCurVertexSRVs.clear(); - mCurPixelSRVs.clear(); +void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv) +{ + if ((rtv && unsetConflictingView(rtv)) || (dsv && unsetConflictingView(dsv))) + { + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + } - invalidateRenderTarget(); + mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv); + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); } -bool StateManager11::setRenderTargets(const RenderTargetArray &renderTargets, - ID3D11DepthStencilView *depthStencil) +void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs, + UINT numRTVs, + ID3D11DepthStencilView *dsv) { - // TODO(jmadill): Use context caps? - UINT drawBuffers = mRenderer->getRendererCaps().maxDrawBuffers; + bool anyDirty = false; - // Apply the render target and depth stencil - size_t arraySize = sizeof(uintptr_t) * drawBuffers; - if (memcmp(renderTargets.data(), mAppliedRTVs.data(), arraySize) == 0 && - reinterpret_cast<uintptr_t>(depthStencil) == mAppliedDSV) + for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex) { - return false; + anyDirty = anyDirty || unsetConflictingView(rtvs[rtvIndex]); } - // The D3D11 blend state is heavily dependent on the current render target. - mBlendStateIsDirty = true; + if (dsv) + { + anyDirty = anyDirty || unsetConflictingView(dsv); + } - for (UINT rtIndex = 0; rtIndex < drawBuffers; rtIndex++) + if (anyDirty) { - mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(renderTargets[rtIndex]); + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); } - mAppliedDSV = reinterpret_cast<uintptr_t>(depthStencil); - mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, renderTargets.data(), - depthStencil); - return true; + mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv); + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); } -void StateManager11::setRenderTarget(ID3D11RenderTargetView *renderTarget, - ID3D11DepthStencilView *depthStencil) +void StateManager11::invalidateVertexAttributeTranslation() { - mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil); + mVertexAttribsNeedTranslation = true; } -void StateManager11::setShaderResource(gl::SamplerType shaderType, - UINT resourceSlot, - ID3D11ShaderResourceView *srv) +void StateManager11::onBeginQuery(Query11 *query) { - auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + mCurrentQueries.insert(query); +} - ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size()); - const SRVRecord &record = currentSRVs[resourceSlot]; +void StateManager11::onDeleteQueryObject(Query11 *query) +{ + mCurrentQueries.erase(query); +} - if (record.srv != reinterpret_cast<uintptr_t>(srv)) +gl::Error StateManager11::onMakeCurrent(const gl::Context *context) +{ + const gl::State &state = context->getGLState(); + + for (Query11 *query : mCurrentQueries) { - auto deviceContext = mRenderer->getDeviceContext(); - if (shaderType == gl::SAMPLER_VERTEX) - { - deviceContext->VSSetShaderResources(resourceSlot, 1, &srv); - } - else + ANGLE_TRY(query->pause()); + } + mCurrentQueries.clear(); + + for (GLenum queryType : QueryTypes) + { + gl::Query *query = state.getActiveQuery(queryType); + if (query != nullptr) { - deviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + Query11 *query11 = GetImplAs<Query11>(query); + ANGLE_TRY(query11->resume()); + mCurrentQueries.insert(query11); } - - currentSRVs.update(resourceSlot, srv); } + + return gl::NoError(); } gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, @@ -856,185 +1528,1548 @@ gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, { if (rangeStart == rangeEnd) { - return gl::Error(GL_NO_ERROR); + 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())); - + gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, currentSRVs.highestUsed())); if (clearRange.empty()) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - auto deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); if (samplerType == gl::SAMPLER_VERTEX) { - deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart), - static_cast<unsigned int>(rangeEnd - rangeStart), + deviceContext->VSSetShaderResources(static_cast<unsigned int>(clearRange.low()), + static_cast<unsigned int>(clearRange.length()), &mNullSRVs[0]); } else { - deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart), - static_cast<unsigned int>(rangeEnd - rangeStart), + deviceContext->PSSetShaderResources(static_cast<unsigned int>(clearRange.low()), + static_cast<unsigned int>(clearRange.length()), &mNullSRVs[0]); } - for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex) + for (size_t samplerIndex : clearRange) { currentSRVs.update(samplerIndex, nullptr); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, +bool StateManager11::unsetConflictingView(ID3D11View *view) +{ + uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view)); + return unsetConflictingSRVs(gl::SAMPLER_VERTEX, resource, nullptr) || + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resource, nullptr); +} + +bool StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, - const gl::ImageIndex &index) + const gl::ImageIndex *index) { auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + bool foundOne = false; + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) { auto &record = currentSRVs[resourceIndex]; if (record.srv && record.resource == resource && - ImageIndexConflictsWithSRV(index, record.desc)) + (!index || ImageIndexConflictsWithSRV(*index, record.desc))) { - setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL); + setShaderResourceInternal<d3d11::ShaderResourceView>( + samplerType, static_cast<UINT>(resourceIndex), nullptr); + foundOne = true; } } + + return foundOne; +} + +void StateManager11::unsetConflictingAttachmentResources( + const gl::FramebufferAttachment *attachment, + ID3D11Resource *resource) +{ + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (attachment->type() == GL_TEXTURE) + { + uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); + const gl::ImageIndex &index = attachment->getTextureImageIndex(); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, &index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, &index); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); + unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, nullptr); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, nullptr); + } } -void StateManager11::initialize(const gl::Caps &caps) +gl::Error StateManager11::initialize(const gl::Caps &caps, const gl::Extensions &extensions) { mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits); mCurPixelSRVs.initialize(caps.maxTextureImageUnits); // Initialize cached NULL SRV block mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); + + mCurrentValueAttribs.resize(caps.maxVertexAttributes); + + mForceSetVertexSamplerStates.resize(caps.maxVertexTextureImageUnits, true); + mForceSetPixelSamplerStates.resize(caps.maxTextureImageUnits, true); + mForceSetComputeSamplerStates.resize(caps.maxComputeTextureImageUnits, true); + + mCurVertexSamplerStates.resize(caps.maxVertexTextureImageUnits); + mCurPixelSamplerStates.resize(caps.maxTextureImageUnits); + mCurComputeSamplerStates.resize(caps.maxComputeTextureImageUnits); + + mShaderConstants.init(caps); + + mIsMultiviewEnabled = extensions.multiview; + mViewportOffsets.resize(1u); + + ANGLE_TRY(mVertexDataManager.initialize()); + + mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); + + return gl::NoError(); +} + +void StateManager11::deinitialize() +{ + mCurrentValueAttribs.clear(); + mInputLayoutCache.clear(); + mVertexDataManager.deinitialize(); + mIndexDataManager.deinitialize(); + + mDriverConstantBufferVS.reset(); + mDriverConstantBufferPS.reset(); + mDriverConstantBufferCS.reset(); } -gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) +gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) { - // Get the color render buffer and serial - // Also extract the render target dimensions and view - unsigned int renderTargetWidth = 0; - unsigned int renderTargetHeight = 0; - DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; - RenderTargetArray framebufferRTVs; - bool missingColorRenderTarget = true; + Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); + + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete()); + + // Check for zero-sized default framebuffer, which is a special case. + // in this case we do not wish to modify any state and just silently return false. + // this will not report any gl error but will cause the calling method to return. + if (framebuffer->id() == 0) + { + ASSERT(!framebuffer11->hasAnyInternalDirtyBit()); + const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize(); + if (size.width == 0 || size.height == 0) + { + return gl::NoError(); + } + } + + RTVArray framebufferRTVs = {{}}; - framebufferRTVs.fill(nullptr); + const auto &colorRTs = framebuffer11->getCachedColorRenderTargets(); - const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); - const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(); + size_t appliedRTIndex = 0; + bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; + const auto &drawStates = framebuffer->getDrawBufferStates(); + gl::DrawBufferMask activeProgramOutputs = + context->getContextState().getState().getProgram()->getActiveOutputVariables(); + UINT maxExistingRT = 0; - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex) { - const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + const RenderTarget11 *renderTarget = colorRTs[rtIndex]; - if (colorbuffer) + // Skip inactive rendertargets if the workaround is enabled. + if (skipInactiveRTs && + (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex])) { - // the draw buffer must be either "none", "back" for the default buffer or the same - // index as this color (in order) - - // check for zero-sized default framebuffer, which is a special case. - // in this case we do not wish to modify any state and just silently return false. - // this will not report any gl error but will cause the calling method to return. - const gl::Extents &size = colorbuffer->getSize(); - if (size.width == 0 || size.height == 0) - { - return gl::Error(GL_NO_ERROR); - } + continue; + } - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); + if (renderTarget) + { + framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get(); + ASSERT(framebufferRTVs[appliedRTIndex]); + maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1; + + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getColorbuffer(rtIndex); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get()); + } + + appliedRTIndex++; + } + + // Get the depth stencil buffers + ID3D11DepthStencilView *framebufferDSV = nullptr; + const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); + if (depthStencilRenderTarget) + { + framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get(); + ASSERT(framebufferDSV); + + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getDepthOrStencilbuffer(); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, + depthStencilRenderTarget->getTexture().get()); + } + + // TODO(jmadill): Use context caps? + ASSERT(maxExistingRT <= static_cast<UINT>(mRenderer->getNativeCaps().maxDrawBuffers)); + + // Apply the render target and depth stencil + mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(), + framebufferDSV); + + return gl::NoError(); +} + +void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex) +{ + mDirtyCurrentValueAttribs.set(attribIndex); + mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); +} + +gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) +{ + const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask(); + const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); + + if (!dirtyActiveAttribs.any()) + { + return gl::NoError(); + } + + const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes(); + const auto &vertexBindings = glState.getVertexArray()->getVertexBindings(); + mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs); + + for (auto attribIndex : dirtyActiveAttribs) + { + if (vertexAttributes[attribIndex].enabled) + continue; + + const auto *attrib = &vertexAttributes[attribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(attribIndex); + TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex]; + currentValueAttrib->currentValueType = currentValue.Type; + currentValueAttrib->attribute = attrib; + currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex]; + + mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex)); + mInputLayoutIsDirty = true; + + ANGLE_TRY(mVertexDataManager.storeCurrentValue(currentValue, currentValueAttrib, + static_cast<size_t>(attribIndex))); + } + + return gl::NoError(); +} - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - ASSERT(framebufferRTVs[colorAttachment]); +void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + if (inputLayout == nullptr) + { + if (!mCurrentInputLayout.empty()) + { + deviceContext->IASetInputLayout(nullptr); + mCurrentInputLayout.clear(); + mInputLayoutIsDirty = true; + } + } + else if (inputLayout->getSerial() != mCurrentInputLayout) + { + deviceContext->IASetInputLayout(inputLayout->get()); + mCurrentInputLayout = inputLayout->getSerial(); + mInputLayoutIsDirty = true; + } +} + +bool StateManager11::queueVertexBufferChange(size_t bufferIndex, + ID3D11Buffer *buffer, + UINT stride, + UINT offset) +{ + if (buffer != mCurrentVertexBuffers[bufferIndex] || + stride != mCurrentVertexStrides[bufferIndex] || + offset != mCurrentVertexOffsets[bufferIndex]) + { + mInputLayoutIsDirty = true; + mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex)); + + mCurrentVertexBuffers[bufferIndex] = buffer; + mCurrentVertexStrides[bufferIndex] = stride; + mCurrentVertexOffsets[bufferIndex] = offset; + return true; + } + + return false; +} + +bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly) +{ + if (offsetOnly != mCurrentVertexOffsets[bufferIndex]) + { + mInputLayoutIsDirty = true; + mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex)); + mCurrentVertexOffsets[bufferIndex] = offsetOnly; + return true; + } + return false; +} - if (missingColorRenderTarget) +void StateManager11::applyVertexBufferChanges() +{ + if (mDirtyVertexBufferRange.empty()) + { + return; + } + + ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS); + + UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low()); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()), + &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start], + &mCurrentVertexOffsets[start]); + + mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0); +} + +void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset) +{ + ID3D11Buffer *native = buffer ? buffer->get() : nullptr; + if (queueVertexBufferChange(0, native, stride, offset)) + { + applyVertexBufferChanges(); + } +} + +gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMode) +{ + const auto &glState = context->getGLState(); + auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + // TODO(jmadill): Use dirty bits. + processFramebufferInvalidation(context); + + // TODO(jmadill): Use dirty bits. + if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty) + { + invalidateTexturesAndSamplers(); + } + + // TODO(jmadill): Use dirty bits. + if (programD3D->areVertexUniformsDirty() || programD3D->areFragmentUniformsDirty()) + { + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); + } + + // Transform feedback affects the stream-out geometry shader. + // TODO(jmadill): Use dirty bits. + if (glState.isTransformFeedbackActiveUnpaused() != mIsTransformFeedbackCurrentlyActiveUnpaused) + { + mIsTransformFeedbackCurrentlyActiveUnpaused = glState.isTransformFeedbackActiveUnpaused(); + invalidateShaders(); + } + + // Swizzling can cause internal state changes with blit shaders. + if (mDirtySwizzles) + { + ANGLE_TRY(generateSwizzles(context)); + mDirtySwizzles = false; + } + + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); + ANGLE_TRY(framebuffer11->markAttachmentsDirty(context)); + + if (framebuffer11->hasAnyInternalDirtyBit()) + { + ASSERT(framebuffer->id() != 0); + framebuffer11->syncInternalState(context); + } + + bool pointDrawMode = (drawMode == GL_POINTS); + if (pointDrawMode != mCurRasterState.pointDrawMode) + { + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Changing from points to not points (or vice-versa) affects the geometry shader. + invalidateShaders(); + } + + // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask + // state changes. + RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget(); + int samples = (firstRT ? firstRT->getSamples() : 0); + unsigned int sampleMask = GetBlendSampleMask(glState, samples); + if (sampleMask != mCurSampleMask) + { + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); + } + + // Changing the vertex attribute state can affect the vertex shader. + gl::VertexArray *vao = glState.getVertexArray(); + VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); + if (vao11->flushAttribUpdates(context)) + { + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); + } + + auto dirtyBitsCopy = mInternalDirtyBits; + mInternalDirtyBits.reset(); + + for (auto dirtyBit : dirtyBitsCopy) + { + switch (dirtyBit) + { + case DIRTY_BIT_RENDER_TARGET: + ANGLE_TRY(syncFramebuffer(context, framebuffer)); + break; + case DIRTY_BIT_VIEWPORT_STATE: + syncViewport(context); + break; + case DIRTY_BIT_SCISSOR_STATE: + syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); + break; + case DIRTY_BIT_RASTERIZER_STATE: + ANGLE_TRY(syncRasterizerState(context, pointDrawMode)); + break; + case DIRTY_BIT_BLEND_STATE: + ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(), + glState.getBlendColor(), sampleMask)); + break; + case DIRTY_BIT_DEPTH_STENCIL_STATE: + ANGLE_TRY(syncDepthStencilState(glState)); + break; + case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE: + // TODO(jmadill): More fine-grained update. + ANGLE_TRY(syncTextures(context)); + break; + case DIRTY_BIT_PROGRAM_UNIFORMS: + ANGLE_TRY(applyUniforms(programD3D)); + break; + case DIRTY_BIT_DRIVER_UNIFORMS: + // This must happen after viewport sync; the viewport affects builtin uniforms. + ANGLE_TRY(applyDriverUniforms(*programD3D)); + break; + case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: + ANGLE_TRY(syncUniformBuffers(context, programD3D)); + break; + case DIRTY_BIT_SHADERS: + ANGLE_TRY(syncProgram(context, drawMode)); + break; + case DIRTY_BIT_CURRENT_VALUE_ATTRIBS: + ANGLE_TRY(syncCurrentValueAttribs(glState)); + break; + default: + UNREACHABLE(); + break; + } + } + + ANGLE_TRY(syncTransformFeedbackBuffers(context)); + + // Check that we haven't set any dirty bits in the flushing of the dirty bits loop. + ASSERT(mInternalDirtyBits.none()); + + return gl::NoError(); +} + +void StateManager11::setShaderResourceShared(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::SharedSRV *srv) +{ + setShaderResourceInternal(shaderType, resourceSlot, srv); + + // TODO(jmadill): Narrower dirty region. + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); +} + +void StateManager11::setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::ShaderResourceView *srv) +{ + setShaderResourceInternal(shaderType, resourceSlot, srv); + + // TODO(jmadill): Narrower dirty region. + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); +} + +void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology) +{ + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } +} + +void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader, + const d3d11::GeometryShader *geometryShader, + const d3d11::PixelShader *pixelShader) +{ + setVertexShader(vertexShader); + setGeometryShader(geometryShader); + setPixelShader(pixelShader); +} + +void StateManager11::setVertexShader(const d3d11::VertexShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedVertexShader) + { + ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0); + mAppliedVertexShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedGeometryShader) + { + ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0); + mAppliedGeometryShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setPixelShader(const d3d11::PixelShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedPixelShader) + { + ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0); + mAppliedPixelShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setComputeShader(const d3d11::ComputeShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedComputeShader) + { + ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0); + mAppliedComputeShader = serial; + // TODO(jmadill): Dirty bits for compute. + } +} + +void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto ¤tSerial = mCurrentConstantBufferVS[slot]; + + mCurrentConstantBufferVSOffset[slot] = 0; + mCurrentConstantBufferVSSize[slot] = 0; + + if (buffer) + { + if (currentSerial != buffer->getSerial()) + { + deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer()); + currentSerial = buffer->getSerial(); + invalidateConstantBuffer(slot); + } + } + else + { + if (!currentSerial.empty()) + { + ID3D11Buffer *nullBuffer = nullptr; + deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer); + currentSerial.clear(); + invalidateConstantBuffer(slot); + } + } +} + +void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto ¤tSerial = mCurrentConstantBufferPS[slot]; + + mCurrentConstantBufferPSOffset[slot] = 0; + mCurrentConstantBufferPSSize[slot] = 0; + + if (buffer) + { + if (currentSerial != buffer->getSerial()) + { + deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer()); + currentSerial = buffer->getSerial(); + invalidateConstantBuffer(slot); + } + } + else + { + if (!currentSerial.empty()) + { + ID3D11Buffer *nullBuffer = nullptr; + deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer); + currentSerial.clear(); + invalidateConstantBuffer(slot); + } + } +} + +void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, + UINT stencilRef) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (depthStencilState) + { + deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef); + } + else + { + deviceContext->OMSetDepthStencilState(nullptr, stencilRef); + } + + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); +} + +void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (blendState) + { + deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF); + } + else + { + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); + } + + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); +} + +void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (rasterizerState) + { + deviceContext->RSSetState(rasterizerState->get()); + } + else + { + deviceContext->RSSetState(nullptr); + } + + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); +} + +void StateManager11::setSimpleViewport(const gl::Extents &extents) +{ + setSimpleViewport(extents.width, extents.height); +} + +void StateManager11::setSimpleViewport(int width, int height) +{ + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast<FLOAT>(width); + viewport.Height = static_cast<FLOAT>(height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + mRenderer->getDeviceContext()->RSSetViewports(1, &viewport); + mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); +} + +void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv, + const d3d11::SamplerState &samplerState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + setShaderResourceInternal(gl::SAMPLER_PIXEL, 0, &srv); + deviceContext->PSSetSamplers(0, 1, samplerState.getPointer()); + + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + mForceSetPixelSamplerStates[0] = true; +} + +void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect) +{ + D3D11_RECT scissorRect; + scissorRect.left = glRect.x; + scissorRect.right = glRect.x + glRect.width; + scissorRect.top = glRect.y; + scissorRect.bottom = glRect.y + glRect.height; + setScissorRectD3D(scissorRect); +} + +void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect) +{ + mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect); + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); +} + +// For each Direct3D sampler of either the pixel or vertex stage, +// looks up the corresponding OpenGL texture image unit and texture type, +// and sets the texture and its addressing/filtering state (or NULL when inactive). +// Sampler mapping needs to be up-to-date on the program object before this is called. +gl::Error StateManager11::applyTextures(const gl::Context *context, gl::SamplerType shaderType) +{ + const auto &glState = context->getGLState(); + const auto &caps = context->getCaps(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + ASSERT(!programD3D->isSamplerMappingDirty()); + + // TODO(jmadill): Use the Program's sampler bindings. + const auto &completeTextures = glState.getCompleteTextureCache(); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); + for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); + ASSERT(textureUnit != -1); + gl::Texture *texture = completeTextures[textureUnit]; + + // A nullptr texture indicates incomplete. + if (texture) + { + gl::Sampler *samplerObject = glState.getSampler(textureUnit); + + const gl::SamplerState &samplerState = + samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); + + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState)); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture)); + } + else + { + GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); + + // Texture is not sampler complete or it is in use by the framebuffer. Bind the + // incomplete texture. + gl::Texture *incompleteTexture = nullptr; + ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture)); + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState())); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture)); + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits + : caps.maxVertexTextureImageUnits; + ANGLE_TRY(clearTextures(shaderType, samplerRange, samplerCount)); + + return gl::NoError(); +} + +gl::Error StateManager11::syncTextures(const gl::Context *context) +{ + ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX)); + ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} + +gl::Error StateManager11::setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &samplerState) +{ +#if !defined(NDEBUG) + // Storage should exist, texture should be complete. Only verified in Debug. + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + TextureStorage *storage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(context, &storage)); + ASSERT(storage); +#endif // !defined(NDEBUG) + + auto *deviceContext = mRenderer->getDeviceContext(); + + if (type == gl::SAMPLER_PIXEL) + { + ASSERT(static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits); + + if (mForceSetPixelSamplerStates[index] || + memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + ASSERT(static_cast<unsigned int>(index) < + mRenderer->getNativeCaps().maxVertexTextureImageUnits); + + if (mForceSetVertexSamplerStates[index] || + memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_COMPUTE) + { + ASSERT(static_cast<unsigned int>(index) < + mRenderer->getNativeCaps().maxComputeTextureImageUnits); + + if (mForceSetComputeSamplerStates[index] || + memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->CSSetSamplers(index, 1, &dxSamplerState); + + mCurComputeSamplerStates[index] = samplerState; + } + + mForceSetComputeSamplerStates[index] = false; + } + else + UNREACHABLE(); + + // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the + // sampler state since having it in contiguous memory makes it possible to memcpy to a constant + // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers. + mShaderConstants.onSamplerChange(type, index, *texture); + + return gl::NoError(); +} + +gl::Error StateManager11::setTexture(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture) +{ + const d3d11::SharedSRV *textureSRV = nullptr; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage)); + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); + + ANGLE_TRY(storage11->getSRV(context, texture->getTextureState(), &textureSRV)); + + // If we get an invalid SRV here, something went wrong in the texture class and we're + // unexpectedly missing the shader resource view. + ASSERT(textureSRV->valid()); + + textureImpl->resetDirty(); + } + + ASSERT( + (type == gl::SAMPLER_PIXEL && + static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits) || + (type == gl::SAMPLER_VERTEX && + static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxVertexTextureImageUnits)); + + setShaderResourceInternal(type, index, textureSRV); + return gl::NoError(); +} + +// Things that affect a program's dirtyness: +// 1. Directly changing the program executable -> triggered in StateManager11::syncState. +// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal. +// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal. +// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState. +// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState. +// 6. An internal shader was used. -> triggered in StateManager11::set*Shader. +// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState. +// TODO(jmadill): Use dirty bits for transform feedback. +gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMode) +{ + Context11 *context11 = GetImplAs<Context11>(context); + ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode)); + + const auto &glState = context->getGLState(); + const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray()); + auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); + + // Binaries must be compiled before the sync. + ASSERT(programD3D->hasVertexExecutableForCachedInputLayout()); + ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode)); + ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout()); + + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr)); + + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); + + ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, + nullptr)); + + const d3d11::VertexShader *vertexShader = + (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr); + + // Skip pixel shader if we're doing rasterizer discard. + const d3d11::PixelShader *pixelShader = nullptr; + if (!glState.getRasterizerState().rasterizerDiscard) + { + pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr); + } + + const d3d11::GeometryShader *geometryShader = nullptr; + if (glState.isTransformFeedbackActiveUnpaused()) + { + geometryShader = + (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr); + } + else + { + geometryShader = + (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr); + } + + setDrawShaders(vertexShader, geometryShader, pixelShader); + + // Explicitly clear the shaders dirty bit. + mInternalDirtyBits.reset(DIRTY_BIT_SHADERS); + + return gl::NoError(); +} + +gl::Error StateManager11::applyVertexBuffer(const gl::Context *context, + GLenum mode, + const DrawCallVertexParams &vertexParams, + bool isIndexedRendering) +{ + const auto &state = context->getGLState(); + const gl::VertexArray *vertexArray = state.getVertexArray(); + VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray); + + if (mVertexAttribsNeedTranslation) + { + ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, &mVertexDataManager, + vertexParams)); + mInputLayoutIsDirty = true; + + // Determine if we need to update attribs on the next draw. + mVertexAttribsNeedTranslation = (vertexArray11->hasActiveDynamicAttrib(context)); + } + + if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != vertexParams.firstVertex()) + { + mLastFirstVertex = vertexParams.firstVertex(); + mInputLayoutIsDirty = true; + } + + if (!mInputLayoutIsDirty) + { + return gl::NoError(); + } + + const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs(); + gl::Program *program = state.getProgram(); + + // Sort the attributes according to ensure we re-use similar input layouts. + AttribIndexArray sortedSemanticIndices; + SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs, + &sortedSemanticIndices, &mCurrentAttributes); + + auto featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + + // If we are using FL 9_3, make sure the first attribute is not instanced + if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty()) + { + if (mCurrentAttributes[0]->divisor > 0) + { + Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes); + if (firstNonInstancedIndex.valid()) { - renderTargetWidth = renderTarget->getWidth(); - renderTargetHeight = renderTarget->getHeight(); - renderTargetFormat = renderTarget->getDXGIFormat(); - missingColorRenderTarget = false; + size_t index = firstNonInstancedIndex.value(); + std::swap(mCurrentAttributes[0], mCurrentAttributes[index]); + std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); } + } + } + + // Update the applied input layout by querying the cache. + ANGLE_TRY(mInputLayoutCache.updateInputLayout(mRenderer, state, mCurrentAttributes, mode, + sortedSemanticIndices, vertexParams)); + + // Update the applied vertex buffers. + ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(context, mCurrentAttributes, mode, + vertexParams.firstVertex(), isIndexedRendering)); + + // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex + // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger + // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the + // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless + // update on the second draw call. + // Hence we clear the flags here, after we've applied vertex data, since we know everything + // is clean. This is a bit of a hack. + vertexArray11->clearDirtyAndPromoteDynamicAttribs(context, vertexParams); + + mInputLayoutIsDirty = false; + return gl::NoError(); +} + +gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, + const void *indices, + GLsizei count, + GLenum type, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround) +{ + const auto &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); + VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); + + GLenum destElementType = + GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround); + + if (!vao11->updateElementArrayStorage(context, type, destElementType, indices) && + !mIndexBufferIsDirty) + { + // No streaming or index buffer application necessary. + return gl::NoError(); + } + + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo(); + ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, destElementType, count, + elementArrayBuffer, indices, indexInfo)); + + ID3D11Buffer *buffer = nullptr; + DXGI_FORMAT bufferFormat = + (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; + + if (indexInfo->storage) + { + Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage); + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDEX), buffer); + } + else + { + IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer); + buffer = indexBuffer->getBuffer().get(); + } + + // Track dirty indices in the index range cache. + indexInfo->srcIndexData.srcIndicesChanged = + syncIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); + + mIndexBufferIsDirty = false; + + vao11->setCachedIndexInfoValid(); + return gl::NoError(); +} + +void StateManager11::setIndexBuffer(ID3D11Buffer *buffer, + DXGI_FORMAT indexFormat, + unsigned int offset) +{ + if (syncIndexBuffer(buffer, indexFormat, offset)) + { + mIndexBufferIsDirty = true; + } +} - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (colorbuffer->type() == GL_TEXTURE) +bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer, + DXGI_FORMAT indexFormat, + unsigned int offset) +{ + if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset) + { + mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset); + + mAppliedIB = buffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = offset; + return true; + } + + return false; +} + +// Vertex buffer is invalidated outside this function. +gl::Error StateManager11::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId) +{ + return mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation( + mRenderer, mCurrentAttributes, startVertex, emulatedInstanceId); +} + +gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture) +{ + if (!texture) + { + return gl::NoError(); + } + + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + ASSERT(textureD3D); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage)); + + if (texStorage) + { + TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); + const gl::TextureState &textureState = texture->getTextureState(); + ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState())); + } + + return gl::NoError(); +} + +gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, + gl::SamplerType type) +{ + const auto &glState = context->getGLState(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(type); + + for (unsigned int i = 0; i < samplerRange; i++) + { + GLenum textureType = programD3D->getSamplerTextureType(type, i); + GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps()); + if (textureUnit != -1) + { + gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getTextureState().swizzleRequired()) { - uintptr_t rtResource = - reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment])); - const gl::ImageIndex &index = colorbuffer->getTextureImageIndex(); - // The index doesn't need to be corrected for the small compressed texture - // workaround - // because a rendertarget is never compressed. - unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); + ANGLE_TRY(generateSwizzle(context, texture)); } } } - // Get the depth stencil buffers - ID3D11DepthStencilView *framebufferDSV = NULL; - const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); - if (depthStencil) + return gl::NoError(); +} + +gl::Error StateManager11::generateSwizzles(const gl::Context *context) +{ + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_VERTEX)); + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} + +gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) +{ + UniformStorage11 *vertexUniformStorage = + GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage()); + UniformStorage11 *fragmentUniformStorage = + GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + const d3d11::Buffer *vertexConstantBuffer = nullptr; + ANGLE_TRY(vertexUniformStorage->getConstantBuffer(mRenderer, &vertexConstantBuffer)); + const d3d11::Buffer *pixelConstantBuffer = nullptr; + ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer)); + + if (vertexUniformStorage->size() > 0 && programD3D->areVertexUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer); + } + + if (fragmentUniformStorage->size() > 0 && programD3D->areFragmentUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer); + } + + unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK; + + if (mCurrentConstantBufferVS[slot] != vertexConstantBuffer->getSerial()) + { + deviceContext->VSSetConstantBuffers(slot, 1, vertexConstantBuffer->getPointer()); + mCurrentConstantBufferVS[slot] = vertexConstantBuffer->getSerial(); + mCurrentConstantBufferVSOffset[slot] = 0; + mCurrentConstantBufferVSSize[slot] = 0; + } + + if (mCurrentConstantBufferPS[slot] != pixelConstantBuffer->getSerial()) + { + deviceContext->PSSetConstantBuffers(slot, 1, pixelConstantBuffer->getPointer()); + mCurrentConstantBufferPS[slot] = pixelConstantBuffer->getSerial(); + mCurrentConstantBufferPSOffset[slot] = 0; + mCurrentConstantBufferPSSize[slot] = 0; + } + + programD3D->markUniformsClean(); + + return gl::NoError(); +} + +gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (!mDriverConstantBufferVS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_VERTEX); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferVS)); + + ID3D11Buffer *driverVSConstants = mDriverConstantBufferVS.get(); + deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &driverVSConstants); + } + + if (!mDriverConstantBufferPS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_PIXEL); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferPS)); + + ID3D11Buffer *driverVSConstants = mDriverConstantBufferPS.get(); + deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &driverVSConstants); + } + + // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve + // constant buffer slots. We update both in the constant buffer if needed. + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_VERTEX, programD3D, + mDriverConstantBufferVS)); + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_PIXEL, programD3D, + mDriverConstantBufferPS)); + + // needed for the point sprite geometry shader + // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3. + if (mRenderer->isES3Capable()) { - RenderTarget11 *depthStencilRenderTarget = NULL; - gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget); - if (error.isError()) + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS.getSerial()) { - return error; + ASSERT(mDriverConstantBufferPS.valid()); + deviceContext->GSSetConstantBuffers(0, 1, mDriverConstantBufferPS.getPointer()); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS.getSerial(); } - ASSERT(depthStencilRenderTarget); + } - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - ASSERT(framebufferDSV); + return gl::NoError(); +} + +gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D) +{ + UniformStorage11 *computeUniformStorage = + GetAs<UniformStorage11>(&programD3D->getComputeUniformStorage()); + ASSERT(computeUniformStorage); + + const d3d11::Buffer *constantBuffer = nullptr; + ANGLE_TRY(computeUniformStorage->getConstantBuffer(mRenderer, &constantBuffer)); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (computeUniformStorage->size() > 0 && programD3D->areComputeUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer); + programD3D->markUniformsClean(); + } + + if (mCurrentComputeConstantBuffer != constantBuffer->getSerial()) + { + deviceContext->CSSetConstantBuffers( + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, + constantBuffer->getPointer()); + mCurrentComputeConstantBuffer = constantBuffer->getSerial(); + } + + if (!mDriverConstantBufferCS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_COMPUTE); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferCS)); + ID3D11Buffer *buffer = mDriverConstantBufferCS.get(); + deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &buffer); + } + + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_COMPUTE, *programD3D, + mDriverConstantBufferCS)); + + return gl::NoError(); +} + +gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D) +{ + unsigned int reservedVertex = mRenderer->getReservedVertexUniformBuffers(); + unsigned int reservedFragment = mRenderer->getReservedFragmentUniformBuffers(); + + programD3D->updateUniformBufferCache(context->getCaps(), reservedVertex, reservedFragment); + + const auto &vertexUniformBuffers = programD3D->getVertexUniformBufferCache(); + const auto &fragmentUniformBuffers = programD3D->getFragmentUniformBufferCache(); + const auto &glState = context->getGLState(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + + for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++) + { + GLint binding = vertexUniformBuffers[bufferIndex]; + + if (binding == -1) + { + continue; + } + + const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) + { + continue; + } + + Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); + const d3d11::Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, + uniformBufferSize, &constantBuffer, + &firstConstant, &numConstants)); + + ASSERT(constantBuffer); + + if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() && + mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset && + mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize) + { + continue; + } + + unsigned int appliedIndex = reservedVertex + static_cast<unsigned int>(bufferIndex); + + if (firstConstant != 0 && uniformBufferSize != 0) + { + ASSERT(numConstants != 0); + deviceContext1->VSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), + &firstConstant, &numConstants); + } + else + { + deviceContext->VSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); + } + + mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial(); + mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset; + mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize; + } + + for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++) + { + GLint binding = fragmentUniformBuffers[bufferIndex]; - // If there is no render buffer, the width, height and format values come from - // the depth stencil - if (missingColorRenderTarget) + if (binding == -1) { - renderTargetWidth = depthStencilRenderTarget->getWidth(); - renderTargetHeight = depthStencilRenderTarget->getHeight(); + continue; } - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (depthStencil->type() == GL_TEXTURE) + const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) { - uintptr_t depthStencilResource = - reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV)); - const gl::ImageIndex &index = depthStencil->getTextureImageIndex(); - // The index doesn't need to be corrected for the small compressed texture workaround - // because a rendertarget is never compressed. - unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); + continue; } + + Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); + const d3d11::Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, + uniformBufferSize, &constantBuffer, + &firstConstant, &numConstants)); + + ASSERT(constantBuffer); + + if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() && + mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset && + mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize) + { + continue; + } + + unsigned int appliedIndex = reservedFragment + static_cast<unsigned int>(bufferIndex); + + if (firstConstant != 0 && uniformBufferSize != 0) + { + deviceContext1->PSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), + &firstConstant, &numConstants); + } + else + { + deviceContext->PSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); + } + + mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial(); + mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset; + mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize; } - if (setRenderTargets(framebufferRTVs, framebufferDSV)) + return gl::NoError(); +} + +gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context) +{ + const auto &glState = context->getGLState(); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // If transform feedback is not active, unbind all buffers + if (!glState.isTransformFeedbackActiveUnpaused()) { - setViewportBounds(renderTargetWidth, renderTargetHeight); + if (mAppliedTFSerial != mEmptySerial) + { + deviceContext->SOSetTargets(0, nullptr, nullptr); + mAppliedTFSerial = mEmptySerial; + } + return gl::NoError(); } - gl::Error error = framebuffer11->invalidateSwizzles(); - if (error.isError()) + gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); + TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback); + if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty()) { - return error; + return gl::NoError(); } - return gl::Error(GL_NO_ERROR); + const std::vector<ID3D11Buffer *> *soBuffers = nullptr; + ANGLE_TRY_RESULT(tf11->getSOBuffers(context), soBuffers); + const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets(); + + deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data()); + + mAppliedTFSerial = tf11->getSerial(); + tf11->onApply(); + + return gl::NoError(); +} + +// DrawCallVertexParams implementation. +DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex, + GLsizei vertexCount, + GLsizei instances) + : mHasIndexRange(nullptr), + mFirstVertex(firstVertex), + mVertexCount(vertexCount), + mInstances(instances), + mBaseVertex(0) +{ +} + +// Use when in a drawElements call. +DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero, + const gl::HasIndexRange &hasIndexRange, + GLint baseVertex, + GLsizei instances) + : mHasIndexRange(&hasIndexRange), + mFirstVertex(), + mVertexCount(0), + mInstances(instances), + mBaseVertex(baseVertex) +{ + if (firstVertexDefinitelyZero) + { + mFirstVertex = baseVertex; + } +} + +GLint DrawCallVertexParams::firstVertex() const +{ + if (!mFirstVertex.valid()) + { + ensureResolved(); + ASSERT(mFirstVertex.valid()); + } + return mFirstVertex.value(); +} + +GLsizei DrawCallVertexParams::vertexCount() const +{ + ensureResolved(); + return mVertexCount; +} + +GLsizei DrawCallVertexParams::instances() const +{ + return mInstances; +} + +void DrawCallVertexParams::ensureResolved() const +{ + if (mHasIndexRange) + { + ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex); + + // Resolve the index range now if we need to. + const auto &indexRange = mHasIndexRange->getIndexRange().value(); + mFirstVertex = mBaseVertex + static_cast<GLint>(indexRange.start); + mVertexCount = static_cast<GLsizei>(indexRange.vertexCount()); + mHasIndexRange = nullptr; + } } } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h index f900882d7e..e48bc83a22 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -11,12 +11,15 @@ #include <array> -#include "libANGLE/angletypes.h" -#include "libANGLE/Data.h" +#include "libANGLE/ContextState.h" #include "libANGLE/State.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" namespace rx { @@ -24,20 +27,147 @@ namespace rx struct RenderTargetDesc; struct Renderer11DeviceCaps; -struct dx_VertexConstants11 +class ShaderConstants11 : angle::NonCopyable { - float depthRange[4]; - float viewAdjust[4]; - float viewCoords[4]; - float viewScale[4]; + public: + ShaderConstants11(); + ~ShaderConstants11(); + + void init(const gl::Caps &caps); + size_t getRequiredBufferSize(gl::SamplerType samplerType) const; + void markDirty(); + + void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); + void setMultiviewWriteToViewportIndex(GLfloat index); + void onViewportChange(const gl::Rectangle &glViewport, + const D3D11_VIEWPORT &dxViewport, + bool is9_3, + bool presentPathFast); + void onSamplerChange(gl::SamplerType samplerType, + unsigned int samplerIndex, + const gl::Texture &texture); + + gl::Error updateBuffer(ID3D11DeviceContext *deviceContext, + gl::SamplerType samplerType, + const ProgramD3D &programD3D, + const d3d11::Buffer &driverConstantBuffer); + + private: + struct Vertex + { + Vertex() + : depthRange{.0f}, + viewAdjust{.0f}, + viewCoords{.0f}, + viewScale{.0f}, + multiviewWriteToViewportIndex{.0f}, + padding{.0f} + { + } + + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; + float viewScale[2]; + // multiviewWriteToViewportIndex is used to select either the side-by-side or layered + // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated + // whenever a multi-view draw framebuffer is made active. + float multiviewWriteToViewportIndex; + + // Added here to manually pad the struct. + float padding; + }; + + struct Pixel + { + Pixel() + : depthRange{.0f}, + viewCoords{.0f}, + depthFront{.0f}, + viewScale{.0f}, + multiviewWriteToViewportIndex(0), + padding(0) + { + } + + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; + float viewScale[2]; + // multiviewWriteToViewportIndex is used to select either the side-by-side or layered + // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated + // whenever a multi-view draw framebuffer is made active. + float multiviewWriteToViewportIndex; + + // Added here to manually pad the struct. + float padding; + }; + + struct Compute + { + Compute() : numWorkGroups{0u}, padding(0u) {} + unsigned int numWorkGroups[3]; + unsigned int padding; // This just pads the struct to 16 bytes + }; + + struct SamplerMetadata + { + SamplerMetadata() : baseLevel(0), internalFormatBits(0), wrapModes(0), padding(0) {} + + int baseLevel; + int internalFormatBits; + int wrapModes; + int padding; // This just pads the struct to 16 bytes + }; + + static_assert(sizeof(SamplerMetadata) == 16u, + "Sampler metadata struct must be one 4-vec / 16 bytes."); + + // Return true if dirty. + bool updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture); + + Vertex mVertex; + bool mVertexDirty; + Pixel mPixel; + bool mPixelDirty; + Compute mCompute; + bool mComputeDirty; + + std::vector<SamplerMetadata> mSamplerMetadataVS; + bool mSamplerMetadataVSDirty; + std::vector<SamplerMetadata> mSamplerMetadataPS; + bool mSamplerMetadataPSDirty; + std::vector<SamplerMetadata> mSamplerMetadataCS; + bool mSamplerMetadataCSDirty; }; -struct dx_PixelConstants11 +class DrawCallVertexParams final : angle::NonCopyable { - float depthRange[4]; - float viewCoords[4]; - float depthFront[4]; - float viewScale[4]; + public: + // Use when in a drawArrays call. + DrawCallVertexParams(GLint firstVertex, GLsizei vertexCount, GLsizei instances); + + // Use when in a drawElements call. + DrawCallVertexParams(bool firstVertexDefinitelyZero, + const gl::HasIndexRange &hasIndexRange, + GLint baseVertex, + GLsizei instances); + + // It should be possible to also use an overload to handle the 'slow' indirect draw path. + // TODO(jmadill): Indirect draw slow path overload. + + GLint firstVertex() const; + GLsizei vertexCount() const; + GLsizei instances() const; + + private: + void ensureResolved() const; + + mutable const gl::HasIndexRange *mHasIndexRange; + mutable Optional<GLint> mFirstVertex; + mutable GLsizei mVertexCount; + GLsizei mInstances; + GLint mBaseVertex; }; class StateManager11 final : angle::NonCopyable @@ -46,62 +176,221 @@ class StateManager11 final : angle::NonCopyable StateManager11(Renderer11 *renderer); ~StateManager11(); - void initialize(const gl::Caps &caps); - void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + gl::Error initialize(const gl::Caps &caps, const gl::Extensions &extensions); + void deinitialize(); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, - const gl::BlendState &blendState, - const gl::ColorF &blendColor, - unsigned int sampleMask); + void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits); - gl::Error setDepthStencilState(const gl::State &glState); + gl::Error updateStateForCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ); - gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); - void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + // These invalidations methods are called externally. - void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar); + // Called from TextureStorage11. + void invalidateBoundViews(); - void updatePresentPath(bool presentPathFastActive, - const gl::FramebufferAttachment *framebufferAttachment); + // Called from VertexArray11::updateVertexAttribStorage. + void invalidateCurrentValueAttrib(size_t attribIndex); - const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; } - const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; } + // Checks are done on a framebuffer state change to trigger other state changes. + // The Context is allowed to be nullptr for these methods, when called in EGL init code. + void invalidateRenderTarget(); - void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + // Called by instanced point sprite emulation. + void invalidateVertexBuffer(); + + // Called by Framebuffer11::syncState for the default sized viewport. + void invalidateViewport(const gl::Context *context); + + // Called by TextureStorage11::markLevelDirty. + void invalidateSwizzles(); + + // Called by the Framebuffer11 and VertexArray11. + void invalidateShaders(); + // Called by VertexArray11 to trigger attribute translation. + void invalidateVertexAttributeTranslation(); + + void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv); + void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv); + + void onBeginQuery(Query11 *query); + void onDeleteQueryObject(Query11 *query); + gl::Error onMakeCurrent(const gl::Context *context); + + void setInputLayout(const d3d11::InputLayout *inputLayout); + + // TODO(jmadill): Migrate to d3d11::Buffer. + bool queueVertexBufferChange(size_t bufferIndex, + ID3D11Buffer *buffer, + UINT stride, + UINT offset); + bool queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly); + void applyVertexBufferChanges(); + + void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset); + + gl::Error updateState(const gl::Context *context, GLenum drawMode); + + void setShaderResourceShared(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::SharedSRV *srv); void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, - ID3D11ShaderResourceView *srv); + const d3d11::ShaderResourceView *srv); + void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology); + + void setDrawShaders(const d3d11::VertexShader *vertexShader, + const d3d11::GeometryShader *geometryShader, + const d3d11::PixelShader *pixelShader); + void setVertexShader(const d3d11::VertexShader *shader); + void setGeometryShader(const d3d11::GeometryShader *shader); + void setPixelShader(const d3d11::PixelShader *shader); + void setComputeShader(const d3d11::ComputeShader *shader); + void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); + void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); + void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef); + void setSimpleBlendState(const d3d11::BlendState *blendState); + void setRasterizerState(const d3d11::RasterizerState *rasterizerState); + void setSimpleViewport(const gl::Extents &viewportExtents); + void setSimpleViewport(int width, int height); + void setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv, + const d3d11::SamplerState &samplerState); + void setSimpleScissorRect(const gl::Rectangle &glRect); + void setScissorRectD3D(const D3D11_RECT &d3dRect); + + // Not handled by an internal dirty bit because of the extra draw parameters. + gl::Error applyVertexBuffer(const gl::Context *context, + GLenum mode, + const DrawCallVertexParams &vertexParams, + bool isIndexedRendering); + + gl::Error applyIndexBuffer(const gl::Context *context, + const void *indices, + GLsizei count, + GLenum type, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround); + + void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); + + gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId); + + // TODO(jmadill): Should be private. + gl::Error applyComputeUniforms(ProgramD3D *programD3D); + + // Only used in testing. + InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + + private: + template <typename SRVType> + void setShaderResourceInternal(gl::SamplerType shaderType, + UINT resourceSlot, + const SRVType *srv); + + bool unsetConflictingView(ID3D11View *view); + bool unsetConflictingSRVs(gl::SamplerType shaderType, + uintptr_t resource, + const gl::ImageIndex *index); + void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment, + ID3D11Resource *resource); + + gl::Error syncBlendState(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask); + + gl::Error syncDepthStencilState(const gl::State &glState); + + gl::Error syncRasterizerState(const gl::Context *context, bool pointDrawMode); + + void syncScissorRectangle(const gl::Rectangle &scissor, bool enabled); + + void syncViewport(const gl::Context *context); + + void checkPresentPath(const gl::Context *context); + + gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer); + gl::Error syncProgram(const gl::Context *context, GLenum drawMode); + + gl::Error syncTextures(const gl::Context *context); + gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType); + + gl::Error setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &sampler); + gl::Error setTexture(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture); + + // Faster than calling setTexture a jillion times gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd); + void handleMultiviewDrawFramebufferChange(const gl::Context *context); - gl::Error syncFramebuffer(const gl::Framebuffer *framebuffer); + gl::Error syncCurrentValueAttribs(const gl::State &glState); - void invalidateRenderTarget(); - void invalidateEverything(); - bool setRenderTargets(const RenderTargetArray &renderTargets, - ID3D11DepthStencilView *depthStencil); - void setRenderTarget(ID3D11RenderTargetView *renderTarget, - ID3D11DepthStencilView *depthStencil); + gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture); + gl::Error generateSwizzlesForShader(const gl::Context *context, gl::SamplerType type); + gl::Error generateSwizzles(const gl::Context *context); - private: - void unsetConflictingSRVs(gl::SamplerType shaderType, - uintptr_t resource, - const gl::ImageIndex &index); - void setViewportBounds(const int width, const int height); + gl::Error applyDriverUniforms(const ProgramD3D &programD3D); + gl::Error applyUniforms(ProgramD3D *programD3D); + + gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D); + gl::Error syncTransformFeedbackBuffers(const gl::Context *context); + + // These are currently only called internally. + void invalidateTexturesAndSamplers(); + void invalidateDriverUniforms(); + void invalidateProgramUniforms(); + void invalidateProgramUniformBuffers(); + void invalidateConstantBuffer(unsigned int slot); + + // Called by the Framebuffer11 directly. + void processFramebufferInvalidation(const gl::Context *context); + + bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); + + enum DirtyBitType + { + DIRTY_BIT_RENDER_TARGET, + DIRTY_BIT_VIEWPORT_STATE, + DIRTY_BIT_SCISSOR_STATE, + DIRTY_BIT_RASTERIZER_STATE, + DIRTY_BIT_BLEND_STATE, + DIRTY_BIT_DEPTH_STENCIL_STATE, + DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE, + DIRTY_BIT_PROGRAM_UNIFORMS, + DIRTY_BIT_DRIVER_UNIFORMS, + DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS, + DIRTY_BIT_SHADERS, + DIRTY_BIT_CURRENT_VALUE_ATTRIBS, + DIRTY_BIT_INVALID, + DIRTY_BIT_MAX = DIRTY_BIT_INVALID, + }; + + using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; Renderer11 *mRenderer; + // Internal dirty bits. + DirtyBits mInternalDirtyBits; + // 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; @@ -110,34 +399,35 @@ class StateManager11 final : angle::NonCopyable 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; + // The viewport offsets are guaranteed to be updated whenever the gl::State::DirtyBits are + // resolved and can be applied to the viewport and scissor whenever the internal viewport and + // scissor bits are resolved. + std::vector<gl::Offset> mViewportOffsets; + // Things needed in viewport state - dx_VertexConstants11 mVertexConstants; - dx_PixelConstants11 mPixelConstants; + ShaderConstants11 mShaderConstants; // Render target variables gl::Extents mViewportBounds; + bool mRenderTargetIsDirty; // EGL_ANGLE_experimental_present_path variables bool mCurPresentPathFastEnabled; int mCurPresentPathFastColorBufferHeight; - // Current RenderTarget state - std::array<uintptr_t, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS> mAppliedRTVs; - uintptr_t mAppliedDSV; + // Queries that are currently active in this state + std::set<Query11 *> mCurrentQueries; // Currently applied textures struct SRVRecord @@ -154,7 +444,8 @@ class StateManager11 final : angle::NonCopyable class SRVCache : angle::NonCopyable { public: - SRVCache() : mHighestUsedSRV(0) {} + SRVCache(); + ~SRVCache(); void initialize(size_t size) { mCurrentSRVs.resize(size); } @@ -175,6 +466,91 @@ class StateManager11 final : angle::NonCopyable // 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; + + // Current applied input layout. + ResourceSerial mCurrentInputLayout; + bool mInputLayoutIsDirty; + bool mVertexAttribsNeedTranslation; + + // Current applied vertex states. + // TODO(jmadill): Figure out how to use ResourceSerial here. + std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexBuffers; + std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides; + std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets; + gl::RangeUI mDirtyVertexBufferRange; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + // Currently applied shaders + ResourceSerial mAppliedVertexShader; + ResourceSerial mAppliedGeometryShader; + ResourceSerial mAppliedPixelShader; + ResourceSerial mAppliedComputeShader; + + // Currently applied sampler states + std::vector<bool> mForceSetVertexSamplerStates; + std::vector<gl::SamplerState> mCurVertexSamplerStates; + + std::vector<bool> mForceSetPixelSamplerStates; + std::vector<gl::SamplerState> mCurPixelSamplerStates; + + std::vector<bool> mForceSetComputeSamplerStates; + std::vector<gl::SamplerState> mCurComputeSamplerStates; + + // Special dirty bit for swizzles. Since they use internal shaders, must be done in a pre-pass. + bool mDirtySwizzles; + + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; + unsigned int mAppliedIBOffset; + bool mIndexBufferIsDirty; + + // Vertex, index and input layouts + VertexDataManager mVertexDataManager; + IndexDataManager mIndexDataManager; + InputLayoutCache mInputLayoutCache; + std::vector<const TranslatedAttribute *> mCurrentAttributes; + Optional<GLint> mLastFirstVertex; + + // ANGLE_multiview. + bool mIsMultiviewEnabled; + + // Driver Constants. + d3d11::Buffer mDriverConstantBufferVS; + d3d11::Buffer mDriverConstantBufferPS; + d3d11::Buffer mDriverConstantBufferCS; + + ResourceSerial mCurrentComputeConstantBuffer; + ResourceSerial mCurrentGeometryConstantBuffer; + + template <typename T> + using VertexConstantBufferArray = + std::array<T, gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS>; + + VertexConstantBufferArray<ResourceSerial> mCurrentConstantBufferVS; + VertexConstantBufferArray<GLintptr> mCurrentConstantBufferVSOffset; + VertexConstantBufferArray<GLsizeiptr> mCurrentConstantBufferVSSize; + + template <typename T> + using FragmentConstantBufferArray = + std::array<T, gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS>; + + FragmentConstantBufferArray<ResourceSerial> mCurrentConstantBufferPS; + FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset; + FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize; + + // Currently applied transform feedback buffers + Serial mAppliedTFSerial; + + Serial mEmptySerial; + + bool mIsTransformFeedbackCurrentlyActiveUnpaused; }; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp new file mode 100644 index 0000000000..1981b5f7b2 --- /dev/null +++ b/src/3rdparty/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::EglBadParameter() << "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::EglBadParameter() << "Texture format not DXGI_FORMAT_NV12"; + } + if (desc.Width < 1 || desc.Height < 1) + { + return egl::EglBadParameter() << "Texture is of size 0"; + } + if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0) + { + return egl::EglBadParameter() << "Texture dimensions are not even"; + } + return egl::NoError(); +} + +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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h new file mode 100644 index 0000000000..304c9dfe53 --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index 42c336c8cf..dcfd06484d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -11,9 +11,9 @@ #include <EGL/eglext.h> #include "libANGLE/features.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.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" @@ -21,6 +21,7 @@ // Precompiled shaders #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h" #ifdef ANGLE_ENABLE_KEYEDMUTEX #define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX @@ -33,22 +34,30 @@ namespace rx namespace { -bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow nativeWindow, EGLint orientation) +// To avoid overflow in QPC to Microseconds calculations, since we multiply +// by kMicrosecondsPerSecond, then the QPC value should not exceed +// (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. +static constexpr int64_t kQPCOverflowThreshold = 0x8637BD05AF7; +static constexpr int64_t kMicrosecondsPerSecond = 1000000; + +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()); + !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow()); } } // anonymous namespace SwapChain11::SwapChain11(Renderer11 *renderer, - NativeWindow nativeWindow, + NativeWindow11 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, - EGLint orientation) - : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + EGLint orientation, + EGLint samples) + : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat), mRenderer(renderer), mWidth(-1), mHeight(-1), @@ -56,33 +65,42 @@ SwapChain11::SwapChain11(Renderer11 *renderer, mAppCreatedShareHandle(mShareHandle != nullptr), mSwapInterval(0), mPassThroughResourcesInit(false), + mNativeWindow(nativeWindow), mFirstSwap(true), mSwapChain(nullptr), -#if defined(ANGLE_ENABLE_D3D11_1) mSwapChain1(nullptr), -#endif mKeyedMutex(nullptr), - mBackBufferTexture(nullptr), - mBackBufferRTView(nullptr), - mBackBufferSRView(nullptr), + mBackBufferTexture(), + mBackBufferRTView(), + mBackBufferSRView(), 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), + mOffscreenTexture(), + mOffscreenRTView(), + mOffscreenSRView(), + mNeedsOffscreenTextureCopy(false), + mOffscreenTextureCopyForSRV(), + mDepthStencilTexture(), + mDepthStencilDSView(), + mDepthStencilSRView(), + mQuadVB(), + mPassThroughSampler(), + mPassThroughIL(), + mPassThroughVS(), + mPassThroughPS(), + mPassThroughRS(), mColorRenderTarget(this, renderer, false), - mDepthStencilRenderTarget(this, renderer, true) + mDepthStencilRenderTarget(this, renderer, true), + mEGLSamples(samples) { // Sanity check that if present path fast is active then we're using the default orientation ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0); + + // Get the performance counter + LARGE_INTEGER counterFreqency = {}; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + ASSERT(success); + + mQPCFrequency = counterFreqency.QuadPart; } SwapChain11::~SwapChain11() @@ -92,52 +110,56 @@ SwapChain11::~SwapChain11() void SwapChain11::release() { -#if defined(ANGLE_ENABLE_D3D11_1) + // TODO(jmadill): Should probably signal that the RenderTarget is dirty. + SafeRelease(mSwapChain1); -#endif 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); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); + mBackBufferSRView.reset(); + mOffscreenTexture.reset(); + mOffscreenRTView.reset(); + mOffscreenSRView.reset(); + mDepthStencilTexture.reset(); + mDepthStencilDSView.reset(); + mDepthStencilSRView.reset(); + mQuadVB.reset(); + mPassThroughSampler.reset(); + mPassThroughIL.reset(); + mPassThroughVS.reset(); + mPassThroughPS.reset(); + mPassThroughRS.reset(); if (!mAppCreatedShareHandle) { - mShareHandle = NULL; + mShareHandle = nullptr; } } void SwapChain11::releaseOffscreenColorBuffer() { - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); + mOffscreenTexture.reset(); + mOffscreenRTView.reset(); + mOffscreenSRView.reset(); + mNeedsOffscreenTextureCopy = false; + mOffscreenTextureCopyForSRV.reset(); } void SwapChain11::releaseOffscreenDepthBuffer() { - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mDepthStencilSRView); + mDepthStencilTexture.reset(); + mDepthStencilDSView.reset(); + mDepthStencilSRView.reset(); } -EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenBuffers(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { if (mNeedsOffscreenTexture) { - EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight); + EGLint result = resetOffscreenColorBuffer(context, backbufferWidth, backbufferHeight); if (result != EGL_SUCCESS) { return result; @@ -156,117 +178,106 @@ EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHei return EGL_SUCCESS; } -EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenColorBuffer(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { ASSERT(mNeedsOffscreenTexture); TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); - ASSERT(device != NULL); + ASSERT(device != nullptr); // 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(); - } + TextureHelper11 previousOffscreenTexture(std::move(mOffscreenTexture)); const int previousWidth = mWidth; const int previousHeight = mHeight; releaseOffscreenColorBuffer(); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - // If the app passed in a share handle, open the resource - // See EGL_ANGLE_d3d_share_handle_client_buffer - if (mAppCreatedShareHandle) + // 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) { - ID3D11Resource *tempResource11; - HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + ASSERT(SUCCEEDED(result)); - if (FAILED(result)) + mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11), + backbufferFormatInfo); + SafeRelease(tempResource11); + } + else if (mD3DTexture != nullptr) { - ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; + mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture), + backbufferFormatInfo); } - - result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); - SafeRelease(tempResource11); - - if (FAILED(result)) + else { - ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; + UNREACHABLE(); } + ASSERT(mOffscreenTexture.valid()); + mOffscreenTexture.getDesc(&offscreenTextureDesc); - // Validate offscreen texture parameters - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - mOffscreenTexture->GetDesc(&offscreenTextureDesc); - - if (offscreenTextureDesc.Width != (UINT)backbufferWidth || - offscreenTextureDesc.Height != (UINT)backbufferHeight || - offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || - offscreenTextureDesc.MipLevels != 1 || - offscreenTextureDesc.ArraySize != 1) + // Fail if the offscreen texture is not renderable. + if ((offscreenTextureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0) { - ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); + ERR() << "Could not use provided offscreen texture, texture not renderable."; release(); - return EGL_BAD_PARAMETER; + return EGL_BAD_SURFACE; } } else { - const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); + const bool useSharedResource = + !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport(); - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; - offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Count = getD3DSamples(); 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)) + gl::Error err = mRenderer->allocateTexture(offscreenTextureDesc, backbufferFormatInfo, + &mOffscreenTexture); + if (err.isError()) { - ERR("Could not create offscreen texture: %08lX", result); + ERR() << "Could not create offscreen texture, " << err; release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } + return EGL_BAD_ALLOC; } - d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); + mOffscreenTexture.setDebugName("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); + IDXGIResource *offscreenTextureResource = nullptr; + HRESULT result = mOffscreenTexture.get()->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); + ERR() << "Could not query offscreen texture resource, " << gl::FmtHR(result); } else { @@ -275,36 +286,49 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe if (FAILED(result)) { - mShareHandle = NULL; - ERR("Could not get offscreen texture shared handle: %08lX", result); + mShareHandle = nullptr; + ERR() << "Could not get offscreen texture shared handle, " << gl::FmtHR(result); } } } } // This may return null if the original texture was created without a keyed mutex. - mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture); + mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture.get()); D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; - offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; - offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; + offscreenRTVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; offscreenRTVDesc.Texture2D.MipSlice = 0; - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + gl::Error err = + mRenderer->allocateResource(offscreenRTVDesc, mOffscreenTexture.get(), &mOffscreenRTView); + ASSERT(!err.isError()); + mOffscreenRTView.setDebugName("Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; - offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; - offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; 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 (offscreenTextureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) + { + err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTexture.get(), + &mOffscreenSRView); + ASSERT(!err.isError()); + mOffscreenSRView.setDebugName("Offscreen back buffer shader resource"); + } + else + { + // Special case for external textures that cannot support sampling. Since internally we + // assume our SwapChain is always readable, we make a copy texture that is compatible. + mNeedsOffscreenTextureCopy = true; + } - if (previousOffscreenTexture != nullptr) + if (previousOffscreenTexture.valid()) { D3D11_BOX sourceBox = {0}; sourceBox.left = 0; @@ -316,14 +340,12 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); const int yoffset = std::max(backbufferHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, - previousOffscreenTexture, 0, &sourceBox); - - SafeRelease(previousOffscreenTexture); + deviceContext->CopySubresourceRegion(mOffscreenTexture.get(), 0, 0, yoffset, 0, + previousOffscreenTexture.get(), 0, &sourceBox); if (mSwapChain) { - swapRect(0, 0, backbufferWidth, backbufferHeight); + swapRect(context, 0, 0, backbufferWidth, backbufferHeight); } } @@ -336,21 +358,38 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe if (mDepthBufferFormat != GL_NONE) { - const d3d11::TextureFormat &depthBufferFormatInfo = - d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + 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.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; - depthStencilTextureDesc.SampleDesc.Count = 1; - depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.SampleDesc.Count = getD3DSamples(); depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + // If there is a multisampled offscreen color texture, the offscreen depth-stencil texture + // must also have the same quality value. + if (mOffscreenTexture.valid() && getD3DSamples() > 1) + { + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture.getDesc(&offscreenTextureDesc); + depthStencilTextureDesc.SampleDesc.Quality = offscreenTextureDesc.SampleDesc.Quality; + } + else + { + depthStencilTextureDesc.SampleDesc.Quality = 0; + } + + // Only create an SRV if it is supported + bool depthStencilSRV = + depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN && + (mRenderer->getRenderer11DeviceCaps().supportsMultisampledDepthStencilSRVs || + depthStencilTextureDesc.SampleDesc.Count <= 1); + if (depthStencilSRV) { depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; } @@ -358,58 +397,56 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe depthStencilTextureDesc.CPUAccessFlags = 0; depthStencilTextureDesc.MiscFlags = 0; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = - device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); - if (FAILED(result)) + gl::Error err = mRenderer->allocateTexture(depthStencilTextureDesc, depthBufferFormatInfo, + &mDepthStencilTexture); + if (err.isError()) { - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + ERR() << "Could not create depthstencil surface for new swap chain, " << err; release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } + return EGL_BAD_ALLOC; } - d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); + mDepthStencilTexture.setDebugName("Offscreen depth stencil texture"); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; - depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; - depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; + depthStencilDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; depthStencilDesc.Flags = 0; depthStencilDesc.Texture2D.MipSlice = 0; - result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + err = mRenderer->allocateResource(depthStencilDesc, mDepthStencilTexture.get(), + &mDepthStencilDSView); + ASSERT(!err.isError()); + mDepthStencilDSView.setDebugName("Offscreen depth stencil view"); - if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + if (depthStencilSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; - depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; + depthStencilSRVDesc.ViewDimension = (mEGLSamples <= 1) + ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; 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"); + err = mRenderer->allocateResource(depthStencilSRVDesc, mDepthStencilTexture.get(), + &mDepthStencilSRView); + ASSERT(!err.isError()); + mDepthStencilSRView.setDebugName("Offscreen depth stencil shader resource"); } } return EGL_SUCCESS; } -EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +EGLint SwapChain11::resize(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight) { TRACE_EVENT0("gpu.angle", "SwapChain11::resize"); ID3D11Device *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { return EGL_BAD_ACCESS; } @@ -427,18 +464,19 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) } // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); + ASSERT(mSwapChain && mBackBufferTexture.valid() && mBackBufferRTView.valid() && + mBackBufferSRView.valid()); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - SafeRelease(mBackBufferSRView); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); + mBackBufferSRView.reset(); // 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); + ERR() << "Error reading swap chain description, " << gl::FmtHR(result); release(); return EGL_BAD_ALLOC; } @@ -447,7 +485,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) if (FAILED(result)) { - ERR("Error resizing swap chain buffers: 0x%08X", result); + ERR() << "Error resizing swap chain buffers, " << gl::FmtHR(result); release(); if (d3d11::isDeviceLostError(result)) @@ -460,39 +498,64 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) } } - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ID3D11Texture2D *backbufferTexture = nullptr; + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast<void **>(&backbufferTexture)); 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"); - } + const auto &format = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + mBackBufferTexture.set(backbufferTexture, format); + mBackBufferTexture.setDebugName("Back buffer texture"); + + gl::Error err = + mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView); + ASSERT(!err.isError()); + mBackBufferRTView.setDebugName("Back buffer render target"); + + err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView); + ASSERT(!err.isError()); + mBackBufferSRView.setDebugName("Back buffer shader resource"); } mFirstSwap = true; - return resetOffscreenBuffers(backbufferWidth, backbufferHeight); + return resetOffscreenBuffers(context, 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; + switch (mOffscreenRenderTargetFormat) + { + case GL_RGBA8: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB8: + case GL_RGB565: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case GL_RGB10_A2: + return DXGI_FORMAT_R10G10B10A2_UNORM; + + case GL_RGBA16F: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + default: + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } } -EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +EGLint SwapChain11::reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) { mSwapInterval = static_cast<unsigned int>(swapInterval); if (mSwapInterval > 4) @@ -505,25 +568,23 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap // If the swap chain already exists, just resize if (mSwapChain != nullptr) { - return resize(backbufferWidth, backbufferHeight); + return resize(context, backbufferWidth, backbufferHeight); } TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { 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. -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(mSwapChain1); -#endif SafeRelease(mSwapChain); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) @@ -532,15 +593,16 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap return EGL_SUCCESS; } - if (mNativeWindow.getNativeWindow()) + if (mNativeWindow->getNativeWindow()) { - HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), - getSwapChainNativeFormat(), - backbufferWidth, backbufferHeight, &mSwapChain); + HRESULT result = mNativeWindow->createSwapChain( + device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth, + backbufferHeight, getD3DSamples(), &mSwapChain); if (FAILED(result)) { - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + ERR() << "Could not create additional swap chains or offscreen surfaces, " + << gl::FmtHR(result); release(); if (d3d11::isDeviceLostError(result)) @@ -555,27 +617,31 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) { -#if defined(ANGLE_ENABLE_D3D11_1) mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); -#endif } - 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); + ID3D11Texture2D *backbufferTex = nullptr; + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast<LPVOID *>(&backbufferTex)); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); + const auto &format = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + mBackBufferTexture.set(backbufferTex, format); + mBackBufferTexture.setDebugName("Back buffer texture"); + + gl::Error err = + mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView); + ASSERT(!err.isError()); + mBackBufferRTView.setDebugName("Back buffer render target"); + + err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView); + ASSERT(!err.isError()); + mBackBufferSRView.setDebugName("Back buffer shader resource view"); } mFirstSwap = true; - return resetOffscreenBuffers(backbufferWidth, backbufferHeight); + return resetOffscreenBuffers(context, backbufferWidth, backbufferHeight); } void SwapChain11::initPassThroughResources() @@ -588,11 +654,11 @@ void SwapChain11::initPassThroughResources() TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); ID3D11Device *device = mRenderer->getDevice(); - ASSERT(device != NULL); + ASSERT(device != nullptr); // Make sure our resources are all not allocated, when we create - ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); - ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + ASSERT(!mQuadVB.valid() && !mPassThroughSampler.valid()); + ASSERT(!mPassThroughIL.valid() && !mPassThroughVS.valid() && !mPassThroughPS.valid()); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; @@ -602,9 +668,9 @@ void SwapChain11::initPassThroughResources() vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; - HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + gl::Error err = mRenderer->allocateResource(vbDesc, &mQuadVB); + ASSERT(!err.isError()); + mQuadVB.setDebugName("Swap chain quad vertex buffer"); D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; @@ -621,9 +687,9 @@ void SwapChain11::initPassThroughResources() samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + err = mRenderer->allocateResource(samplerDesc, &mPassThroughSampler); + ASSERT(!err.isError()); + mPassThroughSampler.setDebugName("Swap chain pass through sampler"); D3D11_INPUT_ELEMENT_DESC quadLayout[] = { @@ -631,17 +697,30 @@ void SwapChain11::initPassThroughResources() { "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"); + InputElementArray quadElements(quadLayout); + ShaderData vertexShaderData(g_VS_Passthrough2D); - result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + err = mRenderer->allocateResource(quadElements, &vertexShaderData, &mPassThroughIL); + ASSERT(!err.isError()); + mPassThroughIL.setDebugName("Swap chain pass through layout"); - result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); + err = mRenderer->allocateResource(vertexShaderData, &mPassThroughVS); + ASSERT(!err.isError()); + mPassThroughVS.setDebugName("Swap chain pass through vertex shader"); + + if (mEGLSamples <= 1) + { + ShaderData pixelShaderData(g_PS_PassthroughRGBA2D); + err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS); + } + else + { + ShaderData pixelShaderData(g_PS_PassthroughRGBA2DMS); + err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS); + } + + ASSERT(!err.isError()); + mPassThroughPS.setDebugName("Swap chain pass through pixel shader"); // Use the default rasterizer state but without culling D3D11_RASTERIZER_DESC rasterizerDesc; @@ -655,26 +734,31 @@ void SwapChain11::initPassThroughResources() 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"); + + err = mRenderer->allocateResource(rasterizerDesc, &mPassThroughRS); + ASSERT(!err.isError()); + mPassThroughRS.setDebugName("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) +EGLint SwapChain11::swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (mNeedsOffscreenTexture) { - EGLint result = copyOffscreenToBackbuffer(x, y, width, height); + EGLint result = copyOffscreenToBackbuffer(context, x, y, width, height); if (result != EGL_SUCCESS) { return result; } } - EGLint result = present(x, y, width, height); + EGLint result = present(context, x, y, width, height); if (result != EGL_SUCCESS) { return result; @@ -685,7 +769,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return EGL_SUCCESS; } -EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { @@ -698,7 +786,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + HRESULT result = + deviceContext->Map(mQuadVB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; @@ -716,7 +805,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, float v1 = y / float(height); float u2 = (x + width) / float(width); float v2 = (y + height) / float(height); - // Invert the quad vertices depending on the surface orientation. if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) { @@ -732,60 +820,43 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); - deviceContext->Unmap(mQuadVB, 0); + deviceContext->Unmap(mQuadVB.get(), 0); - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); - - // Apply state - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + StateManager11 *stateManager = mRenderer->getStateManager(); - static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + constexpr UINT stride = sizeof(d3d11::PositionTexCoordVertex); + stateManager->setSingleVertexBuffer(&mQuadVB, stride, 0); - deviceContext->RSSetState(mPassThroughRS); + // Apply state + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setSimpleBlendState(nullptr); + stateManager->setRasterizerState(&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); + stateManager->setInputLayout(&mPassThroughIL); + stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stateManager->setDrawShaders(&mPassThroughVS, nullptr, &mPassThroughPS); - // Apply render targets - mRenderer->setOneTimeRenderTarget(mBackBufferRTView); + // Apply render targets. Use the proxy context in display. + stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast<FLOAT>(width); - viewport.Height = static_cast<FLOAT>(height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); + stateManager->setSimpleViewport(mWidth, mHeight); // Apply textures - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); - deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, 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->unapplyRenderTargets(); - mRenderer->markAllStateDirty(); - return EGL_SUCCESS; } -EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain11::present(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { @@ -799,9 +870,9 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) HRESULT result = S_OK; -#if defined(ANGLE_ENABLE_D3D11_1) // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. - if (mSwapChain1 != nullptr) + // Dirty rect present is not supported with a multisampled swapchain. + if (mSwapChain1 != nullptr && mEGLSamples <= 1) { if (mFirstSwap) { @@ -818,7 +889,6 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) } } else -#endif { result = mSwapChain->Present(swapInterval, 0); } @@ -826,60 +896,111 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) mFirstSwap = false; // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render - // target. Mark it dirty. + // target. Mark it dirty. Use the proxy context in display since there is none available. mRenderer->getStateManager()->invalidateRenderTarget(); if (result == DXGI_ERROR_DEVICE_REMOVED) { - ERR("Present failed: the D3D11 device was removed: 0x%08X", - mRenderer->getDevice()->GetDeviceRemovedReason()); + ERR() << "Present failed: the D3D11 device was removed, " + << gl::FmtHR(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."); + 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); + ERR() << "Present failed with " << gl::FmtHR(result); } - mNativeWindow.commitChange(); + mNativeWindow->commitChange(); return EGL_SUCCESS; } -ID3D11Texture2D *SwapChain11::getOffscreenTexture() +const TextureHelper11 &SwapChain11::getOffscreenTexture() { return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture; } -ID3D11RenderTargetView *SwapChain11::getRenderTarget() +const d3d11::RenderTargetView &SwapChain11::getRenderTarget() { return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView; } -ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +const d3d11::SharedSRV &SwapChain11::getRenderTargetShaderResource() { - return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView; + if (!mNeedsOffscreenTexture) + { + ASSERT(mBackBufferSRView.valid()); + return mBackBufferSRView; + } + + if (!mNeedsOffscreenTextureCopy) + { + ASSERT(mOffscreenSRView.valid()); + return mOffscreenSRView; + } + + if (!mOffscreenTextureCopyForSRV.valid()) + { + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + + D3D11_TEXTURE2D_DESC offscreenCopyDesc; + mOffscreenTexture.getDesc(&offscreenCopyDesc); + + offscreenCopyDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + offscreenCopyDesc.MiscFlags = 0; + offscreenCopyDesc.CPUAccessFlags = 0; + gl::Error err = mRenderer->allocateTexture(offscreenCopyDesc, backbufferFormatInfo, + &mOffscreenTextureCopyForSRV); + ASSERT(!err.isError()); + mOffscreenTextureCopyForSRV.setDebugName("Offscreen back buffer copy for SRV"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); + + err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTextureCopyForSRV.get(), + &mOffscreenSRView); + ASSERT(!err.isError()); + mOffscreenSRView.setDebugName("Offscreen back buffer shader resource"); + } + + // Need to copy the offscreen texture into the shader-readable copy, since it's external and + // we don't know if the copy is up-to-date. This works around the problem we have when the app + // passes in a texture that isn't shader-readable. + mRenderer->getDeviceContext()->CopyResource(mOffscreenTextureCopyForSRV.get(), + mOffscreenTexture.get()); + return mOffscreenSRView; } -ID3D11DepthStencilView *SwapChain11::getDepthStencil() +const d3d11::DepthStencilView &SwapChain11::getDepthStencil() { return mDepthStencilDSView; } -ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() +const d3d11::SharedSRV &SwapChain11::getDepthStencilShaderResource() { return mDepthStencilSRView; } -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +const TextureHelper11 &SwapChain11::getDepthStencilTexture() { return mDepthStencilTexture; } +void *SwapChain11::getKeyedMutex() +{ + return mKeyedMutex; +} + void SwapChain11::recreate() { // possibly should use this method instead of reset @@ -890,4 +1011,61 @@ void *rx::SwapChain11::getDevice() return mRenderer->getDevice(); } +RenderTargetD3D *SwapChain11::getColorRenderTarget() +{ + return &mColorRenderTarget; +} + +RenderTargetD3D *SwapChain11::getDepthStencilRenderTarget() +{ + return &mDepthStencilRenderTarget; +} + +egl::Error SwapChain11::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) +{ + if (!mSwapChain) + { + return egl::EglNotInitialized() << "Swap chain uninitialized"; + } + + DXGI_FRAME_STATISTICS stats = {}; + HRESULT result = mSwapChain->GetFrameStatistics(&stats); + + if (FAILED(result)) + { + return egl::EglBadAlloc() << "Failed to get frame statistics, " << gl::FmtHR(result); + } + + // Conversion from DXGI_FRAME_STATISTICS to the output values: + // stats.SyncRefreshCount -> msc + // stats.PresentCount -> sbc + // stats.SyncQPCTime -> ust with conversion to microseconds via QueryPerformanceFrequency + *msc = stats.SyncRefreshCount; + *sbc = stats.PresentCount; + + LONGLONG syncQPCValue = stats.SyncQPCTime.QuadPart; + // If the QPC Value is below the overflow threshold, we proceed with + // simple multiply and divide. + if (syncQPCValue < kQPCOverflowThreshold) + { + *ust = syncQPCValue * kMicrosecondsPerSecond / mQPCFrequency; + } + else + { + // Otherwise, calculate microseconds in a round about manner to avoid + // overflow and precision issues. + int64_t wholeSeconds = syncQPCValue / mQPCFrequency; + int64_t leftoverTicks = syncQPCValue - (wholeSeconds * mQPCFrequency); + *ust = wholeSeconds * kMicrosecondsPerSecond + + leftoverTicks * kMicrosecondsPerSecond / mQPCFrequency; + } + + return egl::NoError(); +} + +UINT SwapChain11::getD3DSamples() const +{ + return (mEGLSamples == 0) ? 1 : mEGLSamples; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h index adcd07adb0..eca068210b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -16,39 +16,54 @@ namespace rx { class Renderer11; +class NativeWindow11; -class SwapChain11 : public SwapChainD3D +class SwapChain11 final : public SwapChainD3D { public: SwapChain11(Renderer11 *renderer, - NativeWindow nativeWindow, + NativeWindow11 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, - EGLint orientation); - virtual ~SwapChain11(); - - 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 ID3D11Texture2D *getOffscreenTexture(); - virtual ID3D11RenderTargetView *getRenderTarget(); - virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); - - virtual ID3D11Texture2D *getDepthStencilTexture(); - virtual ID3D11DepthStencilView *getDepthStencil(); - virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); + EGLint orientation, + EGLint samples); + ~SwapChain11() override; + + EGLint resize(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight) override; + EGLint reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) override; + EGLint swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) override; + void recreate() override; + + RenderTargetD3D *getColorRenderTarget() override; + RenderTargetD3D *getDepthStencilRenderTarget() override; + + const TextureHelper11 &getOffscreenTexture(); + const d3d11::RenderTargetView &getRenderTarget(); + const d3d11::SharedSRV &getRenderTargetShaderResource(); + + const TextureHelper11 &getDepthStencilTexture(); + const d3d11::DepthStencilView &getDepthStencil(); + const d3d11::SharedSRV &getDepthStencilShaderResource(); EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } - void *getKeyedMutex() override { return mKeyedMutex; } + void *getKeyedMutex() override; + EGLint getSamples() const { return mEGLSamples; } + + void *getDevice() override; - virtual void *getDevice(); + egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; private: void release(); @@ -56,14 +71,23 @@ class SwapChain11 : public SwapChainD3D void releaseOffscreenColorBuffer(); void releaseOffscreenDepthBuffer(); - EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight); - EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenBuffers(const gl::Context *context, + int backbufferWidth, + int backbufferHeight); + EGLint resetOffscreenColorBuffer(const gl::Context *context, + 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); + EGLint copyOffscreenToBackbuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height); + EGLint present(const gl::Context *context, EGLint x, EGLint y, EGLint width, EGLint height); + UINT getD3DSamples() const; Renderer11 *mRenderer; EGLint mWidth; @@ -73,36 +97,41 @@ class SwapChain11 : public SwapChainD3D unsigned int mSwapInterval; bool mPassThroughResourcesInit; + NativeWindow11 *mNativeWindow; // Handler for the Window that the surface is created for. + bool mFirstSwap; - DXGISwapChain *mSwapChain; -#if defined(ANGLE_ENABLE_D3D11_1) + IDXGISwapChain *mSwapChain; IDXGISwapChain1 *mSwapChain1; -#endif IDXGIKeyedMutex *mKeyedMutex; - ID3D11Texture2D *mBackBufferTexture; - ID3D11RenderTargetView *mBackBufferRTView; - ID3D11ShaderResourceView *mBackBufferSRView; + TextureHelper11 mBackBufferTexture; + d3d11::RenderTargetView mBackBufferRTView; + d3d11::SharedSRV 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; + TextureHelper11 mOffscreenTexture; + d3d11::RenderTargetView mOffscreenRTView; + d3d11::SharedSRV mOffscreenSRView; + bool mNeedsOffscreenTextureCopy; + TextureHelper11 mOffscreenTextureCopyForSRV; + + TextureHelper11 mDepthStencilTexture; + d3d11::DepthStencilView mDepthStencilDSView; + d3d11::SharedSRV mDepthStencilSRView; + + d3d11::Buffer mQuadVB; + d3d11::SamplerState mPassThroughSampler; + d3d11::InputLayout mPassThroughIL; + d3d11::VertexShader mPassThroughVS; + d3d11::PixelShader mPassThroughPS; + d3d11::RasterizerState mPassThroughRS; SurfaceRenderTarget11 mColorRenderTarget; SurfaceRenderTarget11 mDepthStencilRenderTarget; + + EGLint mEGLSamples; + LONGLONG mQPCFrequency; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp index 11b9f76464..b702450ded 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -5,7 +5,8 @@ // // 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. +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 +// texture. #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" @@ -21,6 +22,7 @@ #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" @@ -29,82 +31,79 @@ namespace rx { -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() - : swizzleRed(GL_INVALID_INDEX), - swizzleGreen(GL_INVALID_INDEX), - swizzleBlue(GL_INVALID_INDEX), - swizzleAlpha(GL_INVALID_INDEX) +namespace { + +void InvalidateRenderTarget(const gl::Context *context, RenderTarget11 *renderTarget) +{ + if (renderTarget) + { + renderTarget->signalDirty(context); + } } -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) - : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) +RenderTarget11 *GetRenderTarget(std::unique_ptr<RenderTarget11> *pointer) { + return pointer->get(); } -bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const +template <typename KeyT> +RenderTarget11 *GetRenderTarget(std::pair<KeyT, std::unique_ptr<RenderTarget11>> *pair) { - return swizzleRed == other.swizzleRed && - swizzleGreen == other.swizzleGreen && - swizzleBlue == other.swizzleBlue && - swizzleAlpha == other.swizzleAlpha; + return pair->second.get(); } -bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const +template <typename T> +void InvalidateRenderTargetContainer(const gl::Context *context, T *renderTargetContainer) { - return !(*this == other); + for (auto &rt : *renderTargetContainer) + { + InvalidateRenderTarget(context, GetRenderTarget(&rt)); + } } -TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) - : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) +} // anonymous namespace + +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) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); + 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) +TextureStorage11::TextureStorage11(Renderer11 *renderer, + UINT bindFlags, + UINT miscFlags, + GLenum internalFormat) : mRenderer(renderer), mTopLevel(0), mMipLevels(0), - mInternalFormat(GL_NONE), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())), mTextureWidth(0), mTextureHeight(0), mTextureDepth(0), + mDropStencilTexture(), mBindFlags(bindFlags), mMiscFlags(miscFlags) { - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mLevelSRVs[i] = nullptr; - } } TextureStorage11::~TextureStorage11() { - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mLevelSRVs[level]); - } - - for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) - { - SafeRelease(i->second); - } mSrvCache.clear(); } -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget) +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget) { UINT bindFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; @@ -121,16 +120,17 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Rendere return bindFlags; } -DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels) +DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget, + int levels) { UINT miscFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); if (renderTarget && levels > 1) { - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - - if (dxgiFormatInfo.nativeMipmapSupport(renderer11DeviceCaps.featureLevel)) + if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel)) { miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; } @@ -151,6 +151,8 @@ UINT TextureStorage11::getMiscFlags() const int TextureStorage11::getTopLevel() const { + // Applying top level is meant to be encapsulated inside TextureStorage11. + UNREACHABLE(); return mTopLevel; } @@ -189,24 +191,35 @@ int TextureStorage11::getLevelDepth(int mipLevel) const return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1); } +gl::Error TextureStorage11::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + return getResource(context, outResource); +} + 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 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) +gl::Error TextureStorage11::getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) { - bool swizzleRequired = textureState.swizzleRequired(); - bool mipmapping = gl::IsMipmapFiltered(textureState.samplerState); - unsigned int mipLevels = mipmapping ? (textureState.maxLevel - textureState.baseLevel + 1) : 1; + // 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 - textureState.baseLevel); + // 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) { @@ -217,89 +230,133 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { // We must ensure that the level zero texture is in sync with mipped texture. - gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1)); } if (swizzleRequired) { - verifySwizzleExists(textureState.swizzleRed, textureState.swizzleGreen, - textureState.swizzleBlue, textureState.swizzleAlpha); + verifySwizzleExists(textureState.getSwizzleState()); } - SRVKey key(textureState.baseLevel, mipLevels, swizzleRequired); + // 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. + int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1; + bool hasSmallMips = + (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2); + + bool useDropStencil = (workaround && hasStencil && hasSmallMips); + SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil); + if (useDropStencil) + { + // Ensure drop texture gets created. + DropStencil result = DropStencil::CREATED; + ANGLE_TRY_RESULT(ensureDropStencilTexture(context), result); + + // Clear the SRV cache if necessary. + // TODO(jmadill): Re-use find query result. + auto srvEntry = mSrvCache.find(key); + if (result == DropStencil::CREATED && srvEntry != mSrvCache.end()) + { + mSrvCache.erase(key); + } + } + + ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV)); + + return gl::NoError(); +} + +gl::Error TextureStorage11::getCachedOrCreateSRV(const gl::Context *context, + const SRVKey &key, + const d3d11::SharedSRV **outSRV) +{ auto iter = mSrvCache.find(key); if (iter != mSrvCache.end()) { - *outSRV = iter->second; - return gl::Error(GL_NO_ERROR); + *outSRV = &iter->second; + return gl::NoError(); } - ID3D11Resource *texture = nullptr; - if (swizzleRequired) + const TextureHelper11 *texture = nullptr; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + + if (key.swizzle) { - gl::Error error = getSwizzleTexture(&texture); - if (error.isError()) - { - return error; - } + const auto &swizzleFormat = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); + ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0); + ANGLE_TRY(getSwizzleTexture(&texture)); + format = swizzleFormat.srvFormat; } - else + else if (key.dropStencil) { - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + ASSERT(mDropStencilTexture.valid()); + texture = &mDropStencilTexture; + format = DXGI_FORMAT_R32_FLOAT; } - - ID3D11ShaderResourceView *srv = nullptr; - DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); - gl::Error error = createSRV(textureState.baseLevel, mipLevels, format, texture, &srv); - if (error.isError()) + else { - return error; + ANGLE_TRY(getResource(context, &texture)); + format = mFormatInfo.srvFormat; } - mSrvCache.insert(std::make_pair(key, srv)); - *outSRV = srv; + d3d11::SharedSRV srv; + + ANGLE_TRY(createSRV(context, key.baseLevel, key.mipLevels, format, *texture, &srv)); + + const auto &insertIt = mSrvCache.insert(std::make_pair(key, std::move(srv))); + *outSRV = &insertIt.first->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRVLevel(const gl::Context *context, + int mipLevel, + bool blitSRV, + const d3d11::SharedSRV **outSRV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - if (!mLevelSRVs[mipLevel]) + auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs; + auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs; + + if (!levelSRVs[mipLevel].valid()) { - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) + // Only create a different SRV for blit if blit format is different from regular srv format + if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat) { - return error; + levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy(); } - - error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]); - if (error.isError()) + else { - return error; + const TextureHelper11 *resource = nullptr; + ANGLE_TRY(getResource(context, &resource)); + + DXGI_FORMAT resourceFormat = + blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat; + ANGLE_TRY( + createSRV(context, mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel])); } } - *outSRV = mLevelSRVs[mipLevel]; + *outSRV = &levelSRVs[mipLevel]; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRVLevels(const gl::Context *context, + GLint baseLevel, + GLint maxLevel, + const d3d11::SharedSRV **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) + // 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) @@ -310,245 +367,218 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { // We must ensure that the level zero texture is in sync with mipped texture. - gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1)); } - SRVKey key(baseLevel, mipLevels, false); - auto iter = mSrvCache.find(key); - if (iter != mSrvCache.end()) - { - *outSRV = iter->second; - return gl::Error(GL_NO_ERROR); - } + // TODO(jmadill): Assert we don't need to drop stencil. - ID3D11Resource *texture = nullptr; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + SRVKey key(baseLevel, mipLevels, false, false); + ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV)); - ID3D11ShaderResourceView *srv = nullptr; - error = createSRV(baseLevel, mipLevels, mShaderResourceFormat, texture, &srv); - if (error.isError()) - { - return error; - } - - mSrvCache[key] = srv; - *outSRV = srv; + return gl::NoError(); +} - return gl::Error(GL_NO_ERROR); +const d3d11::Format &TextureStorage11::getFormatSet() const +{ + return mFormatInfo; } -gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +gl::Error TextureStorage11::generateSwizzles(const gl::Context *context, + const gl::SwizzleState &swizzleTarget) { - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); 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 = NULL; - gl::Error error = getSRVLevel(level, &sourceSRV); - if (error.isError()) - { - return error; - } + const d3d11::SharedSRV *sourceSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV)); - ID3D11RenderTargetView *destRTV = NULL; - error = getSwizzleRenderTarget(level, &destRTV); - if (error.isError()) - { - return error; - } + const d3d11::RenderTargetView *destRTV; + ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV)); gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); Blit11 *blitter = mRenderer->getBlitter(); - error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); - if (error.isError()) - { - return error; - } + ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget)); mSwizzleCache[level] = swizzleTarget; } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) +void TextureStorage11::markLevelDirty(int mipLevel) { - if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache)) + if (mipLevel >= 0 && static_cast<size_t>(mipLevel) < mSwizzleCache.size()) { - // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a - // valid swizzle combination - mSwizzleCache[mipLevel] = SwizzleCacheValue(); + // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is + // not a valid swizzle combination + if (mSwizzleCache[mipLevel] != gl::SwizzleState()) + { + // TODO(jmadill): Invalidate specific swizzle. + mRenderer->getStateManager()->invalidateSwizzles(); + mSwizzleCache[mipLevel] = gl::SwizzleState(); + } + } + + if (mDropStencilTexture.valid()) + { + mDropStencilTexture.reset(); } } -void TextureStorage11::invalidateSwizzleCache() +void TextureStorage11::markDirty() { - for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel) { - invalidateSwizzleCacheLevel(mipLevel); + markLevelDirty(static_cast<int>(mipLevel)); } } -gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, - const gl::ImageIndex &index, const gl::Box ©Area) +gl::Error TextureStorage11::updateSubresourceLevel(const gl::Context *context, + const TextureHelper11 &srcTexture, + unsigned int sourceSubresource, + const gl::ImageIndex &index, + const gl::Box ©Area) { - ASSERT(srcTexture); + ASSERT(srcTexture.valid()); - GLint level = index.mipIndex; + const GLint level = index.mipIndex; - invalidateSwizzleCacheLevel(level); + 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; + 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 = NULL; - gl::Error error(GL_NO_ERROR); + const TextureHelper11 *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 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) { - error = getMippedResource(&dstTexture); + ANGLE_TRY(getMippedResource(context, &dstTexture)); } else { - error = getResource(&dstTexture); - } - - if (error.isError()) - { - return error; + ANGLE_TRY(getResource(context, &dstTexture)); } unsigned int dstSubresource = getSubresourceIndex(index); - ASSERT(dstTexture); + ASSERT(dstTexture->valid()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) + 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(); - + Blit11 *blitter = mRenderer->getBlitter(); return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, - dstTexture, dstSubresource, copyArea, texSize, - NULL); + *dstTexture, dstSubresource, copyArea, texSize, nullptr); } - else - { - D3D11_BOX srcBox; - srcBox.left = copyArea.x; - srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatInfo.blockWidth); - srcBox.bottom = copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatInfo.blockHeight); - srcBox.front = copyArea.z; - srcBox.back = copyArea.z + copyArea.depth; - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + 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; - context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, - srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); - return gl::Error(GL_NO_ERROR); - } + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y, + copyArea.z, srcTexture.get(), sourceSubresource, + fullCopy ? nullptr : &srcBox); + return gl::NoError(); } -gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error TextureStorage11::copySubresourceLevel(const gl::Context *context, + const TextureHelper11 &dstTexture, + unsigned int dstSubresource, + const gl::ImageIndex &index, + const gl::Box ®ion) { - ASSERT(dstTexture); + ASSERT(dstTexture.valid()); - ID3D11Resource *srcTexture = NULL; - gl::Error error(GL_NO_ERROR); + const TextureHelper11 *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 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) { - error = getMippedResource(&srcTexture); + ANGLE_TRY(getMippedResource(context, &srcTexture)); } else { - error = getResource(&srcTexture); + ANGLE_TRY(getResource(context, &srcTexture)); } - if (error.isError()) - { - return error; - } - - ASSERT(srcTexture); + ASSERT(srcTexture->valid()); unsigned int srcSubresource = getSubresourceIndex(index); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL. + // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox + // should be nullptr. D3D11_BOX srcBox; - D3D11_BOX *pSrcBox = NULL; + 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(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0); - ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0); - 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; + GLsizei width = region.width; + GLsizei height = region.height; + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr); + + // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures. + if (width == region.width && height == region.height) + { + // 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); + deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y, + region.z, srcTexture->get(), srcSubresource, pSrcBox); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +gl::Error TextureStorage11::generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) { ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); - invalidateSwizzleCacheLevel(destIndex.mipIndex); + markLevelDirty(destIndex.mipIndex); - RenderTargetD3D *source = NULL; - gl::Error error = getRenderTarget(sourceIndex, &source); - if (error.isError()) - { - return error; - } + RenderTargetD3D *source = nullptr; + ANGLE_TRY(getRenderTarget(context, sourceIndex, &source)); - RenderTargetD3D *dest = NULL; - error = getRenderTarget(destIndex, &dest); - if (error.isError()) - { - return error; - } + RenderTargetD3D *dest = nullptr; + ANGLE_TRY(getRenderTarget(context, destIndex, &dest)); - ID3D11ShaderResourceView *sourceSRV = GetAs<RenderTarget11>(source)->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = GetAs<RenderTarget11>(dest)->getRenderTargetView(); + RenderTarget11 *rt11 = GetAs<RenderTarget11>(source); + const d3d11::SharedSRV &sourceSRV = rt11->getBlitShaderResourceView(); + const d3d11::RenderTargetView &destRTV = rt11->getRenderTargetView(); gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); @@ -557,90 +587,75 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); Blit11 *blitter = mRenderer->getBlitter(); - return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, - NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format, - GL_LINEAR, false); + GLenum format = gl::GetUnsizedFormat(source->getInternalFormat()); + return blitter->copyTexture(context, sourceSRV, sourceArea, sourceSize, format, destRTV, + destArea, destSize, nullptr, format, GL_LINEAR, false, false, + false); } -void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState) { - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); for (unsigned int level = 0; level < mMipLevels; level++) { - ASSERT(mSwizzleCache[level] == swizzleTarget); + ASSERT(mSwizzleCache[level] == swizzleState); } } void TextureStorage11::clearSRVCache() { - invalidateSwizzleCache(); - - auto iter = mSrvCache.begin(); - while (iter != mSrvCache.end()) - { - if (!iter->first.swizzle) - { - SafeRelease(iter->second); - iter = mSrvCache.erase(iter); - } - else - { - iter++; - } - } + markDirty(); + mSrvCache.clear(); - for (size_t level = 0; level < ArraySize(mLevelSRVs); level++) + for (size_t level = 0; level < mLevelSRVs.size(); level++) { - SafeRelease(mLevelSRVs[level]); + mLevelSRVs[level].reset(); + mLevelBlitSRVs[level].reset(); } } -gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11::copyToStorage(const gl::Context *context, TextureStorage *destStorage) { ASSERT(destStorage); - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage); + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +gl::Error TextureStorage11::setData(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) { ASSERT(!image->isDirty()); - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) - { - return error; - } - ASSERT(resource); + markLevelDirty(index.mipIndex); + + const TextureHelper11 *resource = nullptr; + ANGLE_TRY(getResource(context, &resource)); + ASSERT(resource && resource->valid()); UINT destSubresource = getSubresourceIndex(index); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(image->getInternalFormat(), type); - gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex)); - bool fullUpdate = (destBox == NULL || *destBox == levelBox); + gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), + getLevelDepth(index.mipIndex)); + bool fullUpdate = (destBox == nullptr || *destBox == levelBox); ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); // TODO(jmadill): Handle compressed formats @@ -649,36 +664,44 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image // with compressed formats in the calling logic. ASSERT(!internalFormatInfo.compressed); - int width = destBox ? destBox->width : static_cast<int>(image->getWidth()); - int height = destBox ? destBox->height : static_cast<int>(image->getHeight()); - int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth()); - UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength); - UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, - unpack.rowLength, unpack.imageHeight); - GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels( - srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels); - - const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); - - size_t outputPixelSize = dxgiFormatInfo.pixelBytes; + const int imageWidth = static_cast<int>(image->getWidth()); + const int width = destBox ? destBox->width : imageWidth; + const int imageHeight = static_cast<int>(image->getHeight()); + const int height = destBox ? destBox->height : imageHeight; + const int imageDepth = static_cast<int>(image->getDepth()); + const int depth = destBox ? destBox->depth : imageDepth; + if (imageWidth < width || imageHeight < height || imageDepth < depth) + fullUpdate = true; + GLuint srcRowPitch = 0; + ANGLE_TRY_RESULT( + internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength), + srcRowPitch); + GLuint srcDepthPitch = 0; + ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch), + srcDepthPitch); + GLuint srcSkipBytes = 0; + ANGLE_TRY_RESULT( + internalFormatInfo.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; - size_t neededSize = bufferDepthPitch * depth; - MemoryBuffer *conversionBuffer = nullptr; + const size_t neededSize = bufferDepthPitch * depth; + angle::MemoryBuffer *conversionBuffer = nullptr; const uint8_t *data = nullptr; - d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type); + LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type); if (loadFunctionInfo.requiresConversion) { - error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer)); loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, srcDepthPitch, conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); @@ -698,264 +721,233 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image ASSERT(destBox); D3D11_BOX destD3DBox; - destD3DBox.left = destBox->x; - destD3DBox.right = destBox->x + destBox->width; - destD3DBox.top = destBox->y; + 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; + destD3DBox.front = destBox->z; + destD3DBox.back = destBox->z + destBox->depth; - immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data, + immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data, bufferRowPitch, bufferDepthPitch); } else { - immediateContext->UpdateSubresource(resource, destSubresource, NULL, data, bufferRowPitch, - bufferDepthPitch); + immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data, + bufferRowPitch, bufferDepthPitch); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture( + const gl::Context *context) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "Drop stencil texture not implemented."; } TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0), + : TextureStorage11(renderer, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + swapchain->getRenderTargetInternalFormat()), mTexture(swapchain->getOffscreenTexture()), - mLevelZeroTexture(NULL), - mLevelZeroRenderTarget(NULL), + mLevelZeroTexture(), + mLevelZeroRenderTarget(nullptr), mUseLevelZeroTexture(false), - mSwizzleTexture(NULL) + mSwizzleTexture() { - mTexture->AddRef(); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; } D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; + mTexture.getDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureWidth = texDesc.Width; mTextureHeight = texDesc.Height; - mTextureDepth = 1; - - mInternalFormat = swapchain->GetRenderTargetInternalFormat(); - - ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps()); - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; -} - -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)), - mTexture(NULL), - mLevelZeroTexture(NULL), - mLevelZeroRenderTarget(NULL), - mUseLevelZeroTexture(false), - mSwizzleTexture(NULL) + 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(), + mHasKeyedMutex(false), + mLevelZeroTexture(), + mLevelZeroRenderTarget(nullptr), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture() { for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; } - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = 1; + mTextureDepth = 1; - if (hintLevelZeroOnly && levels > 1) - { - //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. - ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - mUseLevelZeroTexture = true; - } + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); } -TextureStorage11_2D::~TextureStorage11_2D() +gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context) { for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - if (mAssociatedImages[i] != NULL) + if (mAssociatedImages[i] != nullptr) { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + mAssociatedImages[i]->verifyAssociatedStorageValid(this); - 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 - } - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context)); } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - SafeRelease(mLevelZeroTexture); - SafeDelete(mLevelZeroRenderTarget); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + if (mHasKeyedMutex) { - SafeDelete(mRenderTarget[i]); - SafeRelease(mSwizzleRenderTargets[i]); + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); } + + // Invalidate RenderTargets. + InvalidateRenderTargetContainer(context, &mRenderTarget); + InvalidateRenderTarget(context, mLevelZeroRenderTarget.get()); + + return gl::NoError(); +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ } -gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11_2D::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage); + TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage); + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); 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) + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mTexture); + immediateContext->CopyResource(destResource->get(), mTexture.get()); } - if (mLevelZeroTexture) + if (mLevelZeroTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mLevelZeroTexture); + immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get()); } + + return gl::NoError(); } - else - { - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - dest11->invalidateSwizzleCache(); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) { + bool lastSetting = mUseLevelZeroTexture; + if (useLevelZeroTexture && mMipLevels > 1) { - if (!mUseLevelZeroTexture && mTexture) + if (!mUseLevelZeroTexture && mTexture.valid()) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + 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, NULL); + ASSERT(mLevelZeroTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0, + mTexture.get(), 0, nullptr); } mUseLevelZeroTexture = true; } else { - if (mUseLevelZeroTexture && mLevelZeroTexture) + if (mUseLevelZeroTexture && mLevelZeroTexture.valid()) { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + 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, NULL); + ASSERT(mTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0, + mLevelZeroTexture.get(), 0, nullptr); } mUseLevelZeroTexture = false; } - return gl::Error(GL_NO_ERROR); + if (lastSetting != mUseLevelZeroTexture) + { + // Mark everything as dirty to be conservative. + if (mLevelZeroRenderTarget) + { + mLevelZeroRenderTarget->signalDirty(context); + } + for (auto &renderTarget : mRenderTarget) + { + if (renderTarget) + { + renderTarget->signalDirty(context); + } + } + } + + return gl::NoError(); } -void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); @@ -965,539 +957,569 @@ void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &i } } -bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; + 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; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; + 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] = NULL; - } - } + ASSERT(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) +// 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::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; + 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] != NULL && mAssociatedImages[level] != incomingImage) + 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); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[level]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // 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(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2D::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { if (mUseLevelZeroTexture && mMipLevels > 1) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(1)); - *outResource = mLevelZeroTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mLevelZeroTexture; + return gl::NoError(); } - else - { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2D::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) { // This shouldn't be called unless the zero max LOD workaround is active. ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *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; + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + TextureHelper11 *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 == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (!outputTexture->valid() && 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 = mTextureFormat; - desc.SampleDesc.Count = 1; + 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, NULL, 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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); - d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture)); + outputTexture->setDebugName("TexStorage2D.Texture"); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_2D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); - int level = index.mipIndex; + 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)); - - if (!mRenderTarget[level]) + // 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]) { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(level, &srv); - if (error.isError()) - { - return error; - } - - if (mUseLevelZeroTexture) - { - if (!mLevelZeroRenderTarget) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + level; - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + *outRT = mRenderTarget[level].get(); + return gl::NoError(); + } - 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)); + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(index.mipIndex == 0); + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true)); + } - mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, level, false, &srv)); - ASSERT(outRT); - *outRT = mLevelZeroRenderTarget; - return gl::Error(GL_NO_ERROR); - } + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV)); - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget) { - ID3D11Device *device = mRenderer->getDevice(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; rtvDesc.Texture2D.MipSlice = mTopLevel + level; - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &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, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + mLevelZeroRenderTarget.reset(new TextureRenderTarget11( + std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(), + mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level), + getLevelHeight(level), 1, 0)); } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = mTopLevel + level; - dsvDesc.Flags = 0; + *outRT = mLevelZeroRenderTarget.get(); + return gl::NoError(); + } - ID3D11DepthStencilView *dsv; - HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + 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; - 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); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); - mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + mRenderTarget[level].reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - } - else - { - UNREACHABLE(); - } + *outRT = mRenderTarget[level].get(); + return gl::NoError(); } - ASSERT(outRT); - *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; + + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + + mRenderTarget[level].reset(new TextureRenderTarget11( + std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); + + *outRT = mRenderTarget[level].get(); + return gl::NoError(); } -gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_2D::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(outSRV); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2D.MipLevels = mipLevels; + srvDesc.Texture2D.MipLevels = mipLevels; - ID3D11Resource *srvTexture = texture; + const TextureHelper11 *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. + // 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 != NULL && texture == mLevelZeroTexture); - srvTexture = mLevelZeroTexture; + ANGLE_TRY(ensureTextureExists(1)); + srvTexture = &mLevelZeroTexture; } else { ASSERT(mipLevels == static_cast<int>(mMipLevels)); - ASSERT(mTexture != NULL && texture == mTexture); - srvTexture = mTexture; + ASSERT(mTexture.valid() && 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"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV)); + outSRV->setDebugName("TexStorage2D.SRV"); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_2D::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = 1; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = format.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, NULL, &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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; - d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage2D.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0), - mImage(eglImage), - mCurrentRenderTarget(0), - mSwizzleTexture(nullptr), - mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS, nullptr) +gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture( + const gl::Context *context) { - RenderTargetD3D *renderTargetD3D = nullptr; - mImage->getRenderTarget(&renderTargetD3D); - RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTargetD3D); - mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11); - - mMipLevels = 1; - mTextureFormat = renderTarget11->getDXGIFormat(); - mTextureWidth = renderTarget11->getWidth(); - mTextureHeight = renderTarget11->getHeight(); - mTextureDepth = 1; - mInternalFormat = renderTarget11->getInternalFormat(); - - ID3D11ShaderResourceView *srv = renderTarget11->getShaderResourceView(); - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView *rtv = renderTarget11->getRenderTargetView(); - if (rtv != nullptr) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtv->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - } - else + if (mDropStencilTexture.valid()) { - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + return DropStencil::ALREADY_EXISTS; } - ID3D11DepthStencilView *dsv = renderTarget11->getDepthStencilView(); - if (dsv != nullptr) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsv->GetDesc(&dsvDesc); - mDepthStencilFormat = dsvDesc.Format; - } - else - { - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - } + 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; + + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorage2D.DropStencil"); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo( - dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps()); - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels))); + + return DropStencil::CREATED; } -TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +TextureStorage11_External::TextureStorage11_External( + Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc) + : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat) { - SafeRelease(mSwizzleTexture); - for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++) - { - SafeRelease(mSwizzleRenderTargets[i]); - } + ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12); + StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation()); + mTexture.set(producer->getD3DTexture(), mFormatInfo); + mSubresourceIndex = producer->getArraySlice(); + mTexture.get()->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; } -gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_External::onDestroy(const gl::Context *context) { - gl::Error error = checkForUpdatedRenderTarget(); - if (error.isError()) + if (mHasKeyedMutex) { - return error; + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); } - RenderTarget11 *renderTarget11 = nullptr; - error = getImageRenderTarget(&renderTarget11); - if (error.isError()) - { - return error; - } + return gl::NoError(); +} + +TextureStorage11_External::~TextureStorage11_External() +{ +} + +gl::Error TextureStorage11_External::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) +{ + UNIMPLEMENTED(); + return gl::NoError(); +} - *outResource = renderTarget11->getTexture(); - return gl::Error(GL_NO_ERROR); +void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + ASSERT(index.mipIndex == 0); + mAssociatedImage = image; +} + +void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage); } -gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState, - ID3D11ShaderResourceView **outSRV) +void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) { - gl::Error error = checkForUpdatedRenderTarget(); - if (error.isError()) + ASSERT(index.mipIndex == 0); + ASSERT(mAssociatedImage == expectedImage); + mAssociatedImage = nullptr; +} + +gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) +{ + ASSERT(index.mipIndex == 0); + + if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage) { - return error; + mAssociatedImage->verifyAssociatedStorageValid(this); + + ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context)); } - return TextureStorage11::getSRV(textureState, outSRV); + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **) +gl::Error TextureStorage11_External::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + *outResource = &mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + // Render targets are not supported for external textures + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureStorage11_External::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) +{ + // 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; + + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2D.SRV"); + + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getSwizzleTexture(const TextureHelper11 **outTexture) +{ + UNIMPLEMENTED(); + return gl::InternalError(); +} + +gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) +{ + UNIMPLEMENTED(); + return gl::InternalError(); +} + +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(), + mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) +{ + mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11); + + mMipLevels = 1; + mTextureWidth = renderTarget11->getWidth(); + mTextureHeight = renderTarget11->getHeight(); + mTextureDepth = 1; +} + +TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +{ +} + +gl::Error TextureStorage11_EGLImage::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + ANGLE_TRY(checkForUpdatedRenderTarget(context)); + + RenderTarget11 *renderTarget11 = nullptr; + ANGLE_TRY(getImageRenderTarget(context, &renderTarget11)); + *outResource = &renderTarget11->getTexture(); + return gl::NoError(); +} + +gl::Error TextureStorage11_EGLImage::getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) +{ + ANGLE_TRY(checkForUpdatedRenderTarget(context)); + return TextureStorage11::getSRV(context, textureState, outSRV); +} + +gl::Error TextureStorage11_EGLImage::getMippedResource(const gl::Context *context, + const TextureHelper11 **) { // 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); + return gl::InternalError(); } -gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index, +gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); ASSERT(index.mipIndex == 0); - UNUSED_ASSERTION_VARIABLE(index); - gl::Error error = checkForUpdatedRenderTarget(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(checkForUpdatedRenderTarget(context)); - return mImage->getRenderTarget(outRT); + return mImage->getRenderTarget(context, outRT); } -gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11_EGLImage::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { - ID3D11Resource *sourceResouce = nullptr; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); ASSERT(destStorage); TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage); - ID3D11Resource *destResource = nullptr; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &) @@ -1508,36 +1530,37 @@ void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image1 { } -bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *) +void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) { - return false; } -gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *) +gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &, + Image11 *) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool) +gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context, bool) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_EGLImage::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; desc.Width = mTextureWidth; desc.Height = mTextureHeight; desc.MipLevels = mMipLevels; desc.ArraySize = 1; - desc.Format = mSwizzleTextureFormat; + desc.Format = format.texFormat; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; @@ -1545,68 +1568,43 @@ gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTextu desc.CPUAccessFlags = 0; desc.MiscFlags = 0; - HRESULT result = device->CreateTexture2D(&desc, NULL, &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"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorageEGLImage.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel, - ID3D11RenderTargetView **outRTV) + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; + 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() +gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context) { RenderTarget11 *renderTarget11 = nullptr; - gl::Error error = getImageRenderTarget(&renderTarget11); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getImageRenderTarget(context, &renderTarget11)); if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11)) { @@ -1614,14 +1612,15 @@ gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, +gl::Error TextureStorage11_EGLImage::createSRV(const gl::Context *context, + int baseLevel, int mipLevels, DXGI_FORMAT format, - ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(baseLevel == 0); ASSERT(mipLevels == 1); @@ -1637,163 +1636,129 @@ gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, 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"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorageEGLImage.SRV"); } else { RenderTarget11 *renderTarget = nullptr; - gl::Error error = getImageRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getImageRenderTarget(context, &renderTarget)); ASSERT(texture == renderTarget->getTexture()); - *outSRV = renderTarget->getShaderResourceView(); - (*outSRV)->AddRef(); + *outSRV = renderTarget->getShaderResourceView().makeCopy(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const +gl::Error TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context, + RenderTarget11 **outRT) const { RenderTargetD3D *renderTargetD3D = nullptr; - gl::Error error = mImage->getRenderTarget(&renderTargetD3D); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D)); *outRT = GetAs<RenderTarget11>(renderTargetD3D); - return gl::Error(GL_NO_ERROR); -} - -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)) + 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(), + mLevelZeroTexture(), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture() { - mTexture = NULL; - mSwizzleTexture = NULL; - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mSwizzleRenderTargets[level] = NULL; - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - mAssociatedImages[face][level] = NULL; - mRenderTarget[face][level] = NULL; + mAssociatedImages[face][level] = nullptr; + mRenderTarget[face][level] = nullptr; } } - mLevelZeroTexture = NULL; - mUseLevelZeroTexture = false; - - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - mLevelZeroRenderTarget[face] = NULL; + mLevelZeroRenderTarget[face] = nullptr; } - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // adjust size if needed for compressed textures int height = size; - d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = size; + mMipLevels = mTopLevel + levels; + mTextureWidth = size; mTextureHeight = size; - mTextureDepth = 1; + mTextureDepth = 1; - if (hintLevelZeroOnly && levels > 1) - { - //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. - ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - mUseLevelZeroTexture = true; - } + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); } -TextureStorage11_Cube::~TextureStorage11_Cube() +gl::Error TextureStorage11_Cube::onDestroy(const gl::Context *context) { for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - if (mAssociatedImages[face][level] != NULL) + 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(); - } + mAssociatedImages[face][level]->verifyAssociatedStorageValid(this); + + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context)); } } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - SafeRelease(mLevelZeroTexture); - - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (auto &faceRenderTargets : mRenderTarget) { - SafeDelete(mLevelZeroRenderTarget[face]); + InvalidateRenderTargetContainer(context, &faceRenderTargets); } + InvalidateRenderTargetContainer(context, &mLevelZeroRenderTarget); - 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]); - } - } + return gl::NoError(); +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ } UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const { - if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0) + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && + index.mipIndex == 0) { - UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 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 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) +gl::Error TextureStorage11_Cube::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); @@ -1803,87 +1768,63 @@ gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) { ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. - if (mTexture) + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mTexture); + immediateContext->CopyResource(destResource->get(), mTexture.get()); } - if (mLevelZeroTexture) + if (mLevelZeroTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mLevelZeroTexture); + immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get()); } } else { - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); } - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) { if (useLevelZeroTexture && mMipLevels > 1) { - if (!mUseLevelZeroTexture && mTexture) + if (!mUseLevelZeroTexture && mTexture.valid()) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(1)); // Pull data back from the mipped texture if necessary. - ASSERT(mLevelZeroTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ASSERT(mLevelZeroTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (int face = 0; face < 6; face++) { - context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL); + deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), + D3D11CalcSubresource(0, face, 1), 0, 0, 0, + mTexture.get(), face * mMipLevels, nullptr); } } @@ -1891,346 +1832,286 @@ gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZero } else { - if (mUseLevelZeroTexture && mLevelZeroTexture) + if (mUseLevelZeroTexture && mLevelZeroTexture.valid()) { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); // Pull data back from the level zero texture if necessary. - ASSERT(mTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ASSERT(mTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (int face = 0; face < 6; face++) { - context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL); + deviceContext->CopySubresourceRegion(mTexture.get(), + D3D11CalcSubresource(0, face, mMipLevels), 0, + 0, 0, mLevelZeroTexture.get(), face, nullptr); } } mUseLevelZeroTexture = false; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)) { mAssociatedImages[layerTarget][level] = image; } } } -bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < 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; - } - } + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; - return false; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); - - if (mAssociatedImages[layerTarget][level] == expectedImage) - { - mAssociatedImages[layerTarget][level] = NULL; - } - } - } + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)); + ASSERT(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) +// 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::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)); if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT)) { // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) + 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 NULL too. - gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this); + + // 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(context)); } } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_Cube::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { if (mUseLevelZeroTexture && mMipLevels > 1) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } - - *outResource = mLevelZeroTexture; - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(ensureTextureExists(1)); + *outResource = &mLevelZeroTexture; + return gl::NoError(); } else { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(ensureTextureExists(mMipLevels)); + *outResource = &mTexture; + return gl::NoError(); } } -gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_Cube::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) { // This shouldn't be called unless the zero max LOD workaround is active. ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + 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; + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + TextureHelper11 *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 == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (!outputTexture->valid() && 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 = mTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = gl::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(); + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags(); - HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture)); + outputTexture->setDebugName("TexStorageCube.Texture"); + } - // 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); - } + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const +{ + 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; - d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture"); + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + } + else + { + // Will be used with Texture2D sampler, not TextureCube + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; } - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv)); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { - int faceIndex = index.layerIndex; - int level = index.mipIndex; + const int faceIndex = index.layerIndex; + const int level = index.mipIndex; ASSERT(level >= 0 && level < getLevelCount()); - ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT); + ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::CUBE_FACE_COUNT)); if (!mRenderTarget[faceIndex][level]) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - return error; + ASSERT(index.mipIndex == 0); + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true)); } + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + if (mUseLevelZeroTexture) { if (!mLevelZeroRenderTarget[faceIndex]) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + 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); + rtvDesc.Texture2DArray.ArraySize = 1; - 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)); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv)); - mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11( + std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(), + mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level), + getLevelHeight(level), 1, 0)); } ASSERT(outRT); - *outRT = mLevelZeroRenderTarget[faceIndex]; - return gl::Error(GL_NO_ERROR); + *outRT = mLevelZeroRenderTarget[faceIndex].get(); + return gl::NoError(); } - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIndex; - srvDesc.Texture2DArray.ArraySize = 1; - - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + d3d11::SharedSRV srv; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv)); + d3d11::SharedSRV blitSRV; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV)); } else { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + blitSRV = srv.makeCopy(); } - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); + srv.setDebugName("TexStorageCube.RenderTargetSRV"); - 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); - } - - d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV"); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; - rtvDesc.Texture2DArray.ArraySize = 1; + rtvDesc.Texture2DArray.ArraySize = 1; - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorageCube.RenderTargetRTV"); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - 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, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); + mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Flags = 0; - dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + 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); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); - } + dsvDesc.Texture2DArray.ArraySize = 1; - d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV"); + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + dsv.setDebugName("TexStorageCube.RenderTargetDSV"); - mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - SafeRelease(srv); + mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11( + std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); } else { @@ -2239,215 +2120,237 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re } ASSERT(outRT); - *outRT = mRenderTarget[faceIndex][level]; - return gl::Error(GL_NO_ERROR); + *outRT = mRenderTarget[faceIndex][level].get(); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_Cube::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { 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 d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) + // 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.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + srvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT; } else { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; } - ID3D11Resource *srvTexture = texture; + const TextureHelper11 *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. + // 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 != NULL && texture == mLevelZeroTexture); - srvTexture = mLevelZeroTexture; + ANGLE_TRY(ensureTextureExists(1)); + srvTexture = &mLevelZeroTexture; } else { ASSERT(mipLevels == static_cast<int>(mMipLevels)); - ASSERT(mTexture != NULL && texture == mTexture); - srvTexture = mTexture; + ASSERT(mTexture.valid() && 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"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV)); + outSRV->setDebugName("TexStorageCube.SRV"); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_Cube::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = CUBE_FACE_COUNT; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = gl::CUBE_FACE_COUNT; + desc.Format = format.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, NULL, &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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorageCube.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + 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]); + rtvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT; - 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + 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)) +gl::Error TextureStorage11::initDropStencilTexture(const gl::Context *context, + const gl::ImageIndexIterator &it) { - mTexture = NULL; - mSwizzleTexture = NULL; + const TextureHelper11 *sourceTexture = nullptr; + ANGLE_TRY(getResource(context, &sourceTexture)); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + gl::ImageIndexIterator itCopy = it; + + while (itCopy.hasNext()) { - mAssociatedImages[i] = NULL; - mLevelRenderTargets[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + 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, mDropStencilTexture, subresource, + wholeArea, wholeSize, nullptr)); } - mInternalFormat = internalformat; + return gl::NoError(); +} - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; +gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture( + const gl::Context *context) +{ + if (mDropStencilTexture.valid()) + { + return DropStencil::ALREADY_EXISTS; + } + + 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; + + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorageCube.DropStencil"); + + ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels))); + + return DropStencil::CREATED; +} + +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) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = nullptr; + mLevelRenderTargets[i] = nullptr; + } // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = depth; + mTextureDepth = depth; } -TextureStorage11_3D::~TextureStorage11_3D() +gl::Error TextureStorage11_3D::onDestroy(const gl::Context *context) { for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - if (mAssociatedImages[i] != NULL) + if (mAssociatedImages[i] != nullptr) { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + mAssociatedImages[i]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[i]->recoverFromAssociatedStorage(); - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context)); } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); + InvalidateRenderTargetContainer(context, &mLevelRenderTargets); + InvalidateRenderTargetContainer(context, &mLevelLayerRenderTargets); - for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mLevelLayerRenderTargets.clear(); + return gl::NoError(); +} - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - SafeDelete(mLevelRenderTargets[i]); - SafeRelease(mSwizzleRenderTargets[i]); - } +TextureStorage11_3D::~TextureStorage11_3D() +{ } -void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); @@ -2457,676 +2360,796 @@ void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &i } } -bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - 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; - } + const GLint level = index.mipIndex; - return false; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; + 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] = NULL; - } - } + ASSERT(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) +// 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::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; + 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] != NULL && mAssociatedImages[level] != incomingImage) + 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); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[level]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // 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(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_3D::getResource(const gl::Context *context, + const TextureHelper11 **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 == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + // 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.valid() && 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 = mTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); + 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(); + desc.MiscFlags = getMiscFlags(); - HRESULT result = device->CreateTexture3D(&desc, NULL, &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"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage3D.Texture"); } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_3D::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(outSRV); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + 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); - } + srvDesc.Texture3D.MipLevels = mipLevels; - d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage3D.SRV"); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_3D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { - int mipLevel = index.mipIndex; + const int mipLevel = index.mipIndex; ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); if (!index.hasLayer()) { if (!mLevelRenderTargets[mipLevel]) { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(mipLevel, &srv); - if (error.isError()) - { - return error; - } + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv)); - ID3D11Device *device = mRenderer->getDevice(); + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + 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); - 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"); + rtvDesc.Texture3D.WSize = static_cast<UINT>(-1); - mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage3D.RTV"); - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, + getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel), + getLevelDepth(mipLevel), 0)); } ASSERT(outRT); - *outRT = mLevelRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRT = mLevelRenderTargets[mipLevel].get(); + return gl::NoError(); } - else - { - int layer = index.layerIndex; - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + const int layer = index.layerIndex; - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - 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); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - ASSERT(SUCCEEDED(result)); + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV"); + // TODO, what kind of SRV is expected here? + const d3d11::SharedSRV srv; + const d3d11::SharedSRV blitSRV; - mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + 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; - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage3D.LayerRTV"); - ASSERT(outRT); - *outRT = mLevelLayerRenderTargets[key]; - return gl::Error(GL_NO_ERROR); + mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } + + ASSERT(outRT); + *outRT = mLevelLayerRenderTargets[key].get(); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_3D::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE3D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.Depth = mTextureDepth; - desc.MipLevels = mMipLevels; - desc.Format = mSwizzleTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = format.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, NULL, &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); - } + desc.MiscFlags = 0; - d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage3D.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + 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); + 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"); + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); + mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV"); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -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)) +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 = NULL; - mSwizzleTexture = NULL; - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mSwizzleRenderTargets[level] = NULL; - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = depth; + mTextureDepth = depth; } -TextureStorage11_2DArray::~TextureStorage11_2DArray() +gl::Error TextureStorage11_2DArray::onDestroy(const gl::Context *context) { - for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + for (auto iter : mAssociatedImages) { - if (i->second) + if (iter.second) { - bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + iter.second->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - i->second->recoverFromAssociatedStorage(); - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context)); } } mAssociatedImages.clear(); - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); + InvalidateRenderTargetContainer(context, &mRenderTargets); - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mSwizzleRenderTargets[level]); - } + return gl::NoError(); +} - for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mRenderTargets.clear(); +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ } -void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; ASSERT(0 <= level && level < getLevelCount()); if (0 <= level && level < getLevelCount()) { - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); mAssociatedImages[key] = image; } } -bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); - // 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)); + // 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) +void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); - bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && + (mAssociatedImages[key] == expectedImage)); ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - mAssociatedImages[key] = NULL; - } + 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) +// 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::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); if (mAssociatedImages.find(key) != mAssociatedImages.end()) { - if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) + 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); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[key]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // 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(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2DArray::getResource(const gl::Context *context, + const TextureHelper11 **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 == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + if (!mTexture.valid() && 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 = mTextureFormat; - desc.SampleDesc.Count = 1; + 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, NULL, &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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); - d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage2DArray.Texture"); } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_2DArray::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = mTextureDepth; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2DArray.SRV"); - 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); - } + return gl::NoError(); +} + +gl::Error TextureStorage11_2DArray::createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const +{ + 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 = index.numLayers; - d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(index.hasLayer()); - int mipLevel = index.mipIndex; - int layer = index.layerIndex; + const int mipLevel = index.mipIndex; + const int layer = index.layerIndex; + const int numLayers = index.numLayers; ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - LevelLayerKey key(mipLevel, layer); + LevelLayerRangeKey key(mipLevel, layer, numLayers); if (mRenderTargets.find(key) == mRenderTargets.end()) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + d3d11::SharedSRV srv; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv)); + d3d11::SharedSRV blitSRV; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) { - return error; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV)); } - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = layer; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) + else { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + blitSRV = srv.makeCopy(); } - d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV"); + srv.setDebugName("TexStorage2DArray.RenderTargetSRV"); - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture2DArray.FirstArraySlice = layer; - rtvDesc.Texture2DArray.ArraySize = 1; + rtvDesc.Texture2DArray.ArraySize = numLayers; - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage2DArray.RenderTargetRTV"); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - 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, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); + mRenderTargets[key].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } else { - UNREACHABLE(); + 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 = numLayers; + dsvDesc.Flags = 0; + + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + dsv.setDebugName("TexStorage2DArray.RenderTargetDSV"); + + mRenderTargets[key].reset(new TextureRenderTarget11( + std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } } ASSERT(outRT); - *outRT = mRenderTargets[key]; - return gl::Error(GL_NO_ERROR); + *outRT = mRenderTargets[key].get(); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_2DArray::getSwizzleTexture(const TextureHelper11 **outTexture) { - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = mTextureDepth; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = format.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, NULL, &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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; - d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage2DArray.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + 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; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &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::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2DArray::ensureDropStencilTexture( + const gl::Context *context) +{ + if (mDropStencilTexture.valid()) + { + return DropStencil::ALREADY_EXISTS; } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + 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; + + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorage2DArray.DropStencil"); + + std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth); + + ANGLE_TRY(initDropStencilTexture( + context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data()))); + + return DropStencil::CREATED; } +TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer, + GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels), + internalformat), + mTexture(), + mRenderTarget(nullptr) +{ + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + + mMipLevels = 1; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = 1; + mSamples = samples; + mFixedSampleLocations = fixedSampleLocations; +} + +gl::Error TextureStorage11_2DMultisample::onDestroy(const gl::Context *context) +{ + InvalidateRenderTarget(context, mRenderTarget.get()); + mRenderTarget.reset(); + return gl::NoError(); } + +TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() +{ +} + +gl::Error TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "copyToStorage is unimplemented"; +} + +void TextureStorage11_2DMultisample::associateImage(Image11 *image, const gl::ImageIndex &index) +{ +} + +void TextureStorage11_2DMultisample::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ +} + +void TextureStorage11_2DMultisample::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) +{ +} + +gl::Error TextureStorage11_2DMultisample::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) +{ + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + ANGLE_TRY(ensureTextureExists(1)); + + *outResource = &mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::ensureTextureExists(int mipLevels) +{ + // For Multisampled textures, mipLevels always equals 1. + ASSERT(mipLevels == 1); + + // 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.valid() && mTextureWidth > 0 && mTextureHeight > 0) + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); + + const gl::TextureCaps &textureCaps = + mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(mSamples); + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN); + + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage2DMS.Texture"); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + const int level = index.mipIndex; + ASSERT(level == 0); + + ASSERT(outRT); + if (mRenderTarget) + { + *outRT = mRenderTarget.get(); + return gl::NoError(); + } + + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, level, false, &srv)); + + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV)); + + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + + mRenderTarget.reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, mSamples)); + + *outRT = mRenderTarget.get(); + return gl::NoError(); + } + + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Flags = 0; + + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + + mRenderTarget.reset(new TextureRenderTarget11( + std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, mSamples)); + + *outRT = mRenderTarget.get(); + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2DMS.SRV"); + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getSwizzleTexture(const TextureHelper11 **outTexture) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "getSwizzleTexture is unimplemented."; +} + +gl::Error TextureStorage11_2DMultisample::getSwizzleRenderTarget( + int mipLevel, + const d3d11::RenderTargetView **outRTV) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "getSwizzleRenderTarget is unimplemented."; +} + +gl::ErrorOrResult<TextureStorage11::DropStencil> +TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "Drop stencil texture not implemented."; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h index a88db2f0af..336aa495a8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -10,10 +10,13 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ -#include "libANGLE/Texture.h" #include "libANGLE/Error.h" +#include "libANGLE/Texture.h" #include "libANGLE/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include <array> #include <map> namespace gl @@ -31,69 +34,111 @@ class SwapChain11; class Image11; struct Renderer11DeviceCaps; +template <typename T> +using TexLevelArray = std::array<T, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS>; + +template <typename T> +using CubeFaceArray = std::array<T, gl::CUBE_FACE_COUNT>; + class TextureStorage11 : public TextureStorage { public: - virtual ~TextureStorage11(); + ~TextureStorage11() override; 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; + const d3d11::Format &getFormatSet() const; + gl::Error getSRVLevels(const gl::Context *context, + GLint baseLevel, + GLint maxLevel, + const d3d11::SharedSRV **outSRV); + gl::Error generateSwizzles(const gl::Context *context, const gl::SwizzleState &swizzleTarget); + void markLevelDirty(int mipLevel); + void markDirty(); + + gl::Error updateSubresourceLevel(const gl::Context *context, + const TextureHelper11 &texture, + unsigned int sourceSubresource, + const gl::ImageIndex &index, + const gl::Box ©Area); + + gl::Error copySubresourceLevel(const gl::Context *context, + const TextureHelper11 &dstTexture, + unsigned int dstSubresource, + const gl::ImageIndex &index, + const gl::Box ®ion); + + // TextureStorage virtual functions + int getTopLevel() const override; + bool isRenderTarget() const override; + bool isManaged() const override; bool supportsNativeMipmapFunction() const override; - virtual int getLevelCount() const; + int getLevelCount() const override; + gl::Error generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + gl::Error setData(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) override; + + virtual gl::Error getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV); virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; - - gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - void invalidateSwizzleCacheLevel(int mipLevel); - void invalidateSwizzleCache(); - - 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 gl::Error getResource(const gl::Context *context, + const TextureHelper11 **outResource) = 0; 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); + virtual void verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) = 0; + virtual gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) = 0; protected: - TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags); + 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, ID3D11ShaderResourceView **outSRV); + virtual gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource); + + virtual gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) = 0; + virtual gl::Error getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) = 0; + gl::Error getSRVLevel(const gl::Context *context, + int mipLevel, + bool blitSRV, + const d3d11::SharedSRV **outSRV); + + // Get a version of a depth texture with only depth information, not stencil. + enum DropStencil + { + CREATED, + ALREADY_EXISTS + }; + virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context); + gl::Error initDropStencilTexture(const gl::Context *context, const gl::ImageIndexIterator &it); - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const = 0; + // The baseLevel parameter should *not* have mTopLevel applied. + virtual gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) = 0; - void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + void verifySwizzleExists(const gl::SwizzleState &swizzleState); // Clear all cached non-swizzle SRVs and invalidate the swizzle cache. void clearSRVCache(); @@ -102,32 +147,13 @@ class TextureStorage11 : public TextureStorage int mTopLevel; unsigned int mMipLevels; - GLenum mInternalFormat; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - DXGI_FORMAT mSwizzleTextureFormat; - DXGI_FORMAT mSwizzleShaderResourceFormat; - DXGI_FORMAT mSwizzleRenderTargetFormat; + const d3d11::Format &mFormatInfo; unsigned int mTextureWidth; unsigned int mTextureHeight; unsigned int mTextureDepth; - struct SwizzleCacheValue - { - GLenum swizzleRed; - GLenum swizzleGreen; - GLenum swizzleBlue; - GLenum swizzleAlpha; - - SwizzleCacheValue(); - SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); - - bool operator ==(const SwizzleCacheValue &other) const; - bool operator !=(const SwizzleCacheValue &other) const; - }; - SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray<gl::SwizzleState> mSwizzleCache; + TextureHelper11 mDropStencilTexture; private: const UINT mBindFlags; @@ -135,18 +161,24 @@ class TextureStorage11 : public TextureStorage struct SRVKey { - SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil); bool operator<(const SRVKey &rhs) const; - int baseLevel; - int mipLevels; - bool swizzle; + int baseLevel = 0; // Without mTopLevel applied. + int mipLevels = 0; + bool swizzle = false; + bool dropStencil = false; }; - typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache; + typedef std::map<SRVKey, d3d11::SharedSRV> SRVCache; + + gl::Error getCachedOrCreateSRV(const gl::Context *context, + const SRVKey &key, + const d3d11::SharedSRV **outSRV); SRVCache mSrvCache; - ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray<d3d11::SharedSRV> mLevelSRVs; + TexLevelArray<d3d11::SharedSRV> mLevelBlitSRVs; }; class TextureStorage11_2D : public TextureStorage11 @@ -154,33 +186,48 @@ 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); - virtual ~TextureStorage11_2D(); + ~TextureStorage11_2D() override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getMippedResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error copyToStorage(TextureStorage *destStorage); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - 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); + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; - virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) 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 createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + TexLevelArray<std::unique_ptr<RenderTarget11>> mRenderTarget; + 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). @@ -191,108 +238,179 @@ class TextureStorage11_2D : public TextureStorage11 // 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; + TextureHelper11 mLevelZeroTexture; + std::unique_ptr<RenderTarget11> mLevelZeroRenderTarget; bool mUseLevelZeroTexture; // Swizzle-related variables - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets; + + TexLevelArray<Image11 *> mAssociatedImages; +}; + +class TextureStorage11_External : public TextureStorage11 +{ + public: + TextureStorage11_External(Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc); + ~TextureStorage11_External() override; + + gl::Error onDestroy(const gl::Context *context) override; + + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + protected: + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + + TextureHelper11 mTexture; + int mSubresourceIndex; + bool mHasKeyedMutex; - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + Image11 *mAssociatedImage; }; class TextureStorage11_EGLImage final : public TextureStorage11 { public: - TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage); + 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 getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - gl::Error copyToStorage(TextureStorage *destStorage) override; + gl::Error copyToStorage(const gl::Context *context, 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; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; - gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override; + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; - gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **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 checkForUpdatedRenderTarget(const gl::Context *context); - gl::Error createSRV(int baseLevel, + gl::Error createSRV(const gl::Context *context, + int baseLevel, int mipLevels, DXGI_FORMAT format, - ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const override; + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; - gl::Error getImageRenderTarget(RenderTarget11 **outRT) const; + gl::Error getImageRenderTarget(const gl::Context *context, RenderTarget11 **outRT) const; EGLImageD3D *mImage; uintptr_t mCurrentRenderTarget; // Swizzle-related variables - ID3D11Texture2D *mSwizzleTexture; - std::vector<ID3D11RenderTargetView *> mSwizzleRenderTargets; + TextureHelper11 mSwizzleTexture; + std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets; }; class TextureStorage11_Cube : public TextureStorage11 { public: TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); - virtual ~TextureStorage11_Cube(); + ~TextureStorage11_Cube() override; - virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + gl::Error onDestroy(const gl::Context *context) override; + + UINT getSubresourceIndex(const gl::ImageIndex &index) const override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getMippedResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual gl::Error copyToStorage(TextureStorage *destStorage); + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; - 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); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; - virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override; gl::Error ensureTextureExists(int mipLevels); private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - static const size_t CUBE_FACE_COUNT = 6; + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + gl::Error createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const; - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + CubeFaceArray<TexLevelArray<std::unique_ptr<RenderTarget11>>> mRenderTarget; // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description. - ID3D11Texture2D *mLevelZeroTexture; - RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT]; + TextureHelper11 mLevelZeroTexture; + CubeFaceArray<std::unique_ptr<RenderTarget11>> mLevelZeroRenderTarget; bool mUseLevelZeroTexture; - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets; - Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + CubeFaceArray<TexLevelArray<Image11 *>> mAssociatedImages; }; class TextureStorage11_3D : public TextureStorage11 @@ -300,37 +418,46 @@ 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(); + ~TextureStorage11_3D() override; + + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error getResource(ID3D11Resource **outResource); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; // Handles both layer and non-layer RTs - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - 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); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; typedef std::pair<int, int> LevelLayerKey; - typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; - RenderTargetMap mLevelLayerRenderTargets; + std::map<LevelLayerKey, std::unique_ptr<RenderTarget11>> mLevelLayerRenderTargets; - RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray<std::unique_ptr<RenderTarget11>> mLevelRenderTargets; - ID3D11Texture3D *mTexture; - ID3D11Texture3D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + TextureHelper11 mSwizzleTexture; + TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets; - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray<Image11 *> mAssociatedImages; }; class TextureStorage11_2DArray : public TextureStorage11 @@ -338,37 +465,125 @@ 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(); + ~TextureStorage11_2DArray() override; + + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - 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); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override; private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; + struct LevelLayerRangeKey + { + LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn) + : mipLevel(mipLevelIn), layer(layerIn), numLayers(numLayersIn) + { + } + bool operator<(const LevelLayerRangeKey &other) const + { + if (mipLevel != other.mipLevel) + { + return mipLevel < other.mipLevel; + } + if (layer != other.layer) + { + return layer < other.layer; + } + return numLayers < other.numLayers; + } + int mipLevel; + int layer; + int numLayers; + }; - typedef std::pair<int, int> LevelLayerKey; - typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; - RenderTargetMap mRenderTargets; + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + gl::Error createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const; + + std::map<LevelLayerRangeKey, std::unique_ptr<RenderTarget11>> mRenderTargets; - ID3D11Texture2D *mTexture; + TextureHelper11 mTexture; - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets; - typedef std::map<LevelLayerKey, Image11*> ImageMap; + typedef std::map<LevelLayerRangeKey, Image11 *> ImageMap; ImageMap mAssociatedImages; }; +class TextureStorage11_2DMultisample : public TextureStorage11 +{ + public: + TextureStorage11_2DMultisample(Renderer11 *renderer, + GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations); + ~TextureStorage11_2DMultisample() override; + + gl::Error onDestroy(const gl::Context *context) override; + + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + protected: + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override; + + gl::Error ensureTextureExists(int mipLevels); + + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + + TextureHelper11 mTexture; + std::unique_ptr<RenderTarget11> mRenderTarget; + + unsigned int mSamples; + GLboolean mFixedSampleLocations; +}; } #endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp new file mode 100644 index 0000000000..4b08edf71f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp @@ -0,0 +1,124 @@ +// +// 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), + mSerial(mRenderer->generateSerial()) +{ +} + +TransformFeedback11::~TransformFeedback11() +{ +} + +void TransformFeedback11::begin(GLenum primitiveMode) +{ + // Reset all the cached offsets to the binding offsets + mIsDirty = true; + for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++) + { + const auto &binding = mState.getIndexedBuffer(bindingIdx); + if (binding.get() != nullptr) + { + mBufferOffsets[bindingIdx] = static_cast<UINT>(binding.getOffset()); + } + else + { + mBufferOffsets[bindingIdx] = 0; + } + } +} + +void TransformFeedback11::end() +{ + if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback) + { + mRenderer->getDeviceContext()->Flush(); + } +} + +void TransformFeedback11::pause() +{ +} + +void TransformFeedback11::resume() +{ +} + +void TransformFeedback11::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) +{ +} + +void TransformFeedback11::bindIndexedBuffer(size_t index, + const gl::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( + const gl::Context *context) +{ + 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(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + mBuffers[bindingIdx]); + } + } + + return &mBuffers; +} + +const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const +{ + return mBufferOffsets; +} + +Serial TransformFeedback11::getSerial() const +{ + return mSerial; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h new file mode 100644 index 0000000000..cc9fcc335a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h @@ -0,0 +1,60 @@ +// +// 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/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" +#include "libANGLE/renderer/renderer_utils.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 gl::BindingPointer<gl::Buffer> &binding) override; + void bindIndexedBuffer(size_t index, + const gl::OffsetBindingPointer<gl::Buffer> &binding) override; + + void onApply(); + + bool isDirty() const; + + UINT getNumSOBuffers() const; + gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers(const gl::Context *context); + const std::vector<UINT> &getSOBufferOffsets() const; + + Serial getSerial() const; + + private: + Renderer11 *mRenderer; + + bool mIsDirty; + std::vector<ID3D11Buffer *> mBuffers; + std::vector<UINT> mBufferOffsets; + + Serial mSerial; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp index 213ce31817..29185a9d93 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp @@ -11,9 +11,15 @@ #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #if defined (ANGLE_ENABLE_WINDOWS_STORE) -using namespace ABI::Windows::Foundation; +#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 @@ -41,7 +47,6 @@ void Trim11::trim() #if defined (ANGLE_ENABLE_WINDOWS_STORE) ID3D11Device* device = mRenderer->getDevice(); - // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above. IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device); if (dxgiDevice3) { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h index 4741e81601..69fa05a57b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -13,9 +13,7 @@ #include "libANGLE/angletypes.h" #include "libANGLE/Error.h" -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -typedef void* EventRegistrationToken; -#else +#if defined(ANGLE_ENABLE_WINDOWS_STORE) #include <EventToken.h> #endif diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp new file mode 100644 index 0000000000..97c29415ed --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp @@ -0,0 +1,413 @@ +// +// 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/bitset_utils.h" +#include "libANGLE/Context.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Context11.h" + +using namespace angle; + +namespace rx +{ + +namespace +{ +OnBufferDataDirtyChannel *GetBufferBroadcastChannel(Buffer11 *buffer11, + IndexStorageType storageType) +{ + switch (storageType) + { + case IndexStorageType::Direct: + return buffer11->getDirectBroadcastChannel(); + case IndexStorageType::Static: + return buffer11->getStaticBroadcastChannel(); + case IndexStorageType::Dynamic: + return buffer11 ? buffer11->getStaticBroadcastChannel() : nullptr; + default: + UNREACHABLE(); + return nullptr; + } +} +} // anonymous namespace + +VertexArray11::VertexArray11(const gl::VertexArrayState &data) + : VertexArrayImpl(data), + mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE), + mTranslatedAttribs(data.getMaxAttribs()), + mCurrentArrayBuffers(data.getMaxAttribs()), + mCurrentElementArrayBuffer(), + mOnArrayBufferDataDirty(), + mOnElementArrayBufferDataDirty(this, mCurrentArrayBuffers.size()), + mAppliedNumViewsToDivisor(1), + mLastElementType(GL_NONE), + mLastDrawElementsOffset(0), + mCurrentElementArrayStorage(IndexStorageType::Invalid), + mCachedIndexInfoValid(false) +{ + for (size_t attribIndex = 0; attribIndex < mCurrentArrayBuffers.size(); ++attribIndex) + { + mOnArrayBufferDataDirty.emplace_back(this, attribIndex); + } +} + +VertexArray11::~VertexArray11() +{ +} + +void VertexArray11::destroy(const gl::Context *context) +{ + for (auto &buffer : mCurrentArrayBuffers) + { + if (buffer.get()) + { + buffer.set(context, nullptr); + } + } + + mCurrentElementArrayBuffer.set(context, nullptr); +} + +void VertexArray11::syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) +{ + ASSERT(dirtyBits.any()); + + // Generate a state serial. This serial is used in the program class to validate the cached + // input layout, and skip recomputation in the fast path. + Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer(); + mCurrentStateSerial = renderer->generateSerial(); + + // TODO(jmadill): Individual attribute invalidation. + renderer->getStateManager()->invalidateVertexBuffer(); + + for (auto dirtyBit : dirtyBits) + { + if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) + { + mCachedIndexInfoValid = false; + mLastElementType = GL_NONE; + } + else + { + size_t index = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); + // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings + ASSERT(index == mState.getBindingIndexFromAttribIndex(index)); + mAttribsToUpdate.set(index); + } + } +} + +bool VertexArray11::flushAttribUpdates(const gl::Context *context) +{ + if (mAttribsToUpdate.any()) + { + const auto &activeLocations = + context->getGLState().getProgram()->getActiveAttribLocationsMask(); + + // Skip attrib locations the program doesn't use. + gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations; + + for (auto toUpdateIndex : activeToUpdate) + { + mAttribsToUpdate.reset(toUpdateIndex); + updateVertexAttribStorage(context, toUpdateIndex); + } + + return true; + } + + return false; +} + +bool VertexArray11::updateElementArrayStorage(const gl::Context *context, + GLenum elementType, + GLenum destElementType, + const void *indices) +{ + unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); + + if (mCachedIndexInfoValid && mLastElementType == elementType && + offset == mLastDrawElementsOffset) + { + // Dynamic index buffers must be re-streamed every draw. + return (mCurrentElementArrayStorage == IndexStorageType::Dynamic); + } + + gl::Buffer *newBuffer = mState.getElementArrayBuffer().get(); + gl::Buffer *oldBuffer = mCurrentElementArrayBuffer.get(); + bool needsTranslation = false; + IndexStorageType newStorageType = ClassifyIndexStorage( + context->getGLState(), newBuffer, elementType, destElementType, offset, &needsTranslation); + + if (newBuffer != oldBuffer) + { + mCurrentElementArrayBuffer.set(context, newBuffer); + } + + if (newStorageType != mCurrentElementArrayStorage || newBuffer != oldBuffer) + { + Buffer11 *newBuffer11 = SafeGetImplAs<Buffer11>(newBuffer); + + auto *newChannel = GetBufferBroadcastChannel(newBuffer11, newStorageType); + + mCurrentElementArrayStorage = newStorageType; + mOnElementArrayBufferDataDirty.bind(newChannel); + needsTranslation = true; + } + + if (mLastDrawElementsOffset != offset) + { + needsTranslation = true; + mLastDrawElementsOffset = offset; + } + + if (mLastElementType != elementType) + { + needsTranslation = true; + mLastElementType = elementType; + } + + // TODO(jmadill): We should probably promote static usage immediately, because this can change + // the storage type for dynamic buffers. + return needsTranslation || !mCachedIndexInfoValid; +} + +void VertexArray11::updateVertexAttribStorage(const gl::Context *context, size_t attribIndex) +{ + const auto &attrib = mState.getVertexAttribute(attribIndex); + const auto &binding = mState.getBindingFromAttribIndex(attribIndex); + + // Note: having an unchanged storage type doesn't mean the attribute is clean. + auto oldStorageType = mAttributeStorageTypes[attribIndex]; + auto newStorageType = ClassifyAttributeStorage(attrib, binding); + + mAttributeStorageTypes[attribIndex] = newStorageType; + + StateManager11 *stateManager = GetImplAs<Context11>(context)->getRenderer()->getStateManager(); + + 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); + stateManager->invalidateVertexAttributeTranslation(); + + if (oldStorageType == VertexStorageType::DYNAMIC) + { + ASSERT(mDynamicAttribsMask[attribIndex]); + mDynamicAttribsMask.reset(attribIndex); + } + } + + gl::Buffer *oldBufferGL = mCurrentArrayBuffers[attribIndex].get(); + gl::Buffer *newBufferGL = binding.getBuffer().get(); + Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr; + Buffer11 *newBuffer11 = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr; + + if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType) + { + OnBufferDataDirtyChannel *newChannel = nullptr; + + if (newStorageType == VertexStorageType::CURRENT_VALUE) + { + stateManager->invalidateCurrentValueAttrib(attribIndex); + } + else if (newBuffer11 != nullptr) + { + // Note that for static callbacks, promotion to a static buffer from a dynamic buffer + // means we need to tag dynamic buffers with static callbacks. + switch (newStorageType) + { + case VertexStorageType::DIRECT: + newChannel = newBuffer11->getDirectBroadcastChannel(); + break; + case VertexStorageType::STATIC: + case VertexStorageType::DYNAMIC: + newChannel = newBuffer11->getStaticBroadcastChannel(); + break; + default: + UNREACHABLE(); + break; + } + } + + mOnArrayBufferDataDirty[attribIndex].bind(newChannel); + mCurrentArrayBuffers[attribIndex].set(context, binding.getBuffer().get()); + } +} + +bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context) +{ + flushAttribUpdates(context); + const auto &activeLocations = + context->getGLState().getProgram()->getActiveAttribLocationsMask(); + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + return activeDynamicAttribs.any(); +} + +gl::Error VertexArray11::updateDirtyAndDynamicAttribs(const gl::Context *context, + VertexDataManager *vertexDataManager, + const DrawCallVertexParams &vertexParams) +{ + flushAttribUpdates(context); + + const auto &glState = context->getGLState(); + const gl::Program *program = glState.getProgram(); + const auto &activeLocations = program->getActiveAttribLocationsMask(); + const auto &attribs = mState.getVertexAttributes(); + const auto &bindings = mState.getVertexBindings(); + mAppliedNumViewsToDivisor = + (program != nullptr && program->usesMultiview()) ? program->getNumViews() : 1; + + if (mAttribsToTranslate.any()) + { + // Skip attrib locations the program doesn't use, saving for the next frame. + gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations); + + for (auto dirtyAttribIndex : dirtyActiveAttribs) + { + mAttribsToTranslate.reset(dirtyAttribIndex); + + auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex); + + // Record basic attrib info + translatedAttrib->attribute = &attribs[dirtyAttribIndex]; + translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; + translatedAttrib->currentValueType = currentValue.Type; + translatedAttrib->divisor = + translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; + + switch (mAttributeStorageTypes[dirtyAttribIndex]) + { + case VertexStorageType::DIRECT: + VertexDataManager::StoreDirectAttrib(translatedAttrib); + break; + case VertexStorageType::STATIC: + { + ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib)); + break; + } + case VertexStorageType::CURRENT_VALUE: + // Current value attribs are managed by the StateManager11. + break; + default: + UNREACHABLE(); + break; + } + } + } + + if (mDynamicAttribsMask.any()) + { + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + if (activeDynamicAttribs.none()) + { + return gl::NoError(); + } + + for (auto dynamicAttribIndex : activeDynamicAttribs) + { + auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex); + + // Record basic attrib info + dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; + dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex]; + dynamicAttrib->currentValueType = currentValue.Type; + dynamicAttrib->divisor = + dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; + } + + ANGLE_TRY(vertexDataManager->storeDynamicAttribs( + context, &mTranslatedAttribs, activeDynamicAttribs, vertexParams.firstVertex(), + vertexParams.vertexCount(), vertexParams.instances())); + } + + return gl::NoError(); +} + +const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const +{ + return mTranslatedAttribs; +} + +void VertexArray11::signal(size_t channelID, const gl::Context *context) +{ + if (channelID == mAttributeStorageTypes.size()) + { + mCachedIndexInfoValid = false; + mLastElementType = GL_NONE; + mLastDrawElementsOffset = 0; + } + else + { + ASSERT(mAttributeStorageTypes[channelID] != VertexStorageType::CURRENT_VALUE); + + // This can change a buffer's storage, we'll need to re-check. + mAttribsToUpdate.set(channelID); + + // Changing the vertex attribute state can affect the vertex shader. + Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer(); + renderer->getStateManager()->invalidateShaders(); + } +} + +void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::Context *context, + const DrawCallVertexParams &vertexParams) +{ + const gl::State &state = context->getGLState(); + 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); + if (activeDynamicAttribs.any()) + { + VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs, + vertexParams.vertexCount()); + } +} + +void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews) +{ + if (mAppliedNumViewsToDivisor != numViews) + { + mAppliedNumViewsToDivisor = numViews; + mAttribsToUpdate.set(); + } +} + +TranslatedIndexData *VertexArray11::getCachedIndexInfo() +{ + return &mCachedIndexInfo; +} + +void VertexArray11::setCachedIndexInfoValid() +{ + mCachedIndexInfoValid = true; +} + +bool VertexArray11::isCachedIndexInfoValid() const +{ + return mCachedIndexInfoValid; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h index b397140e71..4cdc92531d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -9,23 +9,91 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ +#include "libANGLE/Framebuffer.h" #include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/signal_utils.h" namespace rx { class Renderer11; -class VertexArray11 : public VertexArrayImpl +class VertexArray11 : public VertexArrayImpl, public OnBufferDataDirtyReceiver { public: - VertexArray11(const gl::VertexArray::Data &data) - : VertexArrayImpl(data) - { - } - virtual ~VertexArray11() {} + VertexArray11(const gl::VertexArrayState &data); + ~VertexArray11() override; + void destroy(const gl::Context *context) override; + + void syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) override; + // This will flush any pending attrib updates and then check the dynamic attribs mask. + bool hasActiveDynamicAttrib(const gl::Context *context); + gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context, + VertexDataManager *vertexDataManager, + const DrawCallVertexParams &vertexParams); + void clearDirtyAndPromoteDynamicAttribs(const gl::Context *context, + const DrawCallVertexParams &vertexParams); + + const std::vector<TranslatedAttribute> &getTranslatedAttribs() const; + + // SignalReceiver implementation + void signal(size_t channelID, const gl::Context *context) override; + + Serial getCurrentStateSerial() const { return mCurrentStateSerial; } + + // In case of a multi-view program change, we have to update all attributes so that the divisor + // is adjusted. + void markAllAttributeDivisorsForAdjustment(int numViews); + + bool flushAttribUpdates(const gl::Context *context); + + // Returns true if the element array buffer needs to be translated. + bool updateElementArrayStorage(const gl::Context *context, + GLenum elementType, + GLenum destElementType, + const void *indices); + + TranslatedIndexData *getCachedIndexInfo(); + void setCachedIndexInfoValid(); + bool isCachedIndexInfoValid() const; + + private: + void updateVertexAttribStorage(const gl::Context *context, 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<gl::BindingPointer<gl::Buffer>> mCurrentArrayBuffers; + gl::BindingPointer<gl::Buffer> mCurrentElementArrayBuffer; + + std::vector<OnBufferDataDirtyBinding> mOnArrayBufferDataDirty; + OnBufferDataDirtyBinding mOnElementArrayBufferDataDirty; + + Serial mCurrentStateSerial; + + // The numViews value used to adjust the divisor. + int mAppliedNumViewsToDivisor; + + // If the index buffer needs re-streaming. + GLenum mLastElementType; + unsigned int mLastDrawElementsOffset; + IndexStorageType mCurrentElementArrayStorage; + TranslatedIndexData mCachedIndexInfo; + bool mCachedIndexInfoValid; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp index 098cefcd53..611bd0f18b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -19,92 +19,88 @@ namespace rx { -VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) + : mRenderer(renderer), + mBuffer(), + mBufferSize(0), + mDynamicUsage(false), + mMappedResourceData(nullptr) { - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; - mMappedResourceData = NULL; } VertexBuffer11::~VertexBuffer11() { - ASSERT(mMappedResourceData == NULL); - SafeRelease(mBuffer); + ASSERT(mMappedResourceData == nullptr); } gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) { - SafeRelease(mBuffer); - + mBuffer.reset(); 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.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); - } + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer)); if (dynamicUsage) { - d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)"); + mBuffer.setDebugName("VertexBuffer11 (dynamic)"); } else { - d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)"); + mBuffer.setDebugName("VertexBuffer11 (static)"); } } - mBufferSize = size; + mBufferSize = size; mDynamicUsage = dynamicUsage; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error VertexBuffer11::mapResource() { - if (mMappedResourceData == NULL) + if (mMappedResourceData == nullptr) { ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + HRESULT result = + dxContext->Map(mBuffer.get(), 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); + return gl::OutOfMemory() + << "Failed to map internal vertex buffer, " << gl::FmtHR(result); } - mMappedResourceData = reinterpret_cast<uint8_t*>(mappedResource.pData); + mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void VertexBuffer11::hintUnmapResource() { - if (mMappedResourceData != NULL) + if (mMappedResourceData != nullptr) { ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - mMappedResourceData = NULL; + mMappedResourceData = nullptr; } } gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -112,81 +108,33 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri unsigned int offset, const uint8_t *sourceData) { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "Internal vertex buffer is not initialized."; } - int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib)); + int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding)); // This will map the resource if it isn't already mapped. - gl::Error error = mapResource(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mapResource()); uint8_t *output = mMappedResourceData + offset; const uint8_t *input = sourceData; - if (instances == 0 || attrib.divisor == 0) + if (instances == 0 || binding.getDivisor() == 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); + const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = + d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); + ASSERT(vertexFormatInfo.copyFunction != nullptr); vertexFormatInfo.copyFunction(input, inputStride, count, output); - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementCount = 0; - if (attrib.enabled) - { - 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 = mRenderer->getRenderer11DeviceCaps().featureLevel; - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(formatType, featureLevel); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); - unsigned int elementSize = dxgiFormatInfo.pixelBytes; - if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return gl::Error(GL_NO_ERROR); - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return gl::Error(GL_NO_ERROR); - } + return gl::NoError(); } unsigned int VertexBuffer11::getBufferSize() const @@ -202,34 +150,35 @@ gl::Error VertexBuffer11::setBufferSize(unsigned int size) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } gl::Error VertexBuffer11::discard() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "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); + HRESULT result = dxContext->Map(mBuffer.get(), 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); + return gl::OutOfMemory() << "Failed to map internal buffer for discarding, " + << gl::FmtHR(result); } - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -ID3D11Buffer *VertexBuffer11::getBuffer() const +const d3d11::Buffer &VertexBuffer11::getBuffer() const { return mBuffer; } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h index 773c4474e1..ab619ae503 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h @@ -12,6 +12,7 @@ #include <stdint.h> #include "libANGLE/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -21,11 +22,13 @@ class VertexBuffer11 : public VertexBuffer { public: explicit VertexBuffer11(Renderer11 *const renderer); - virtual ~VertexBuffer11(); - virtual gl::Error initialize(unsigned int size, bool dynamicUsage); + gl::Error initialize(unsigned int size, bool dynamicUsage) override; + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -33,29 +36,27 @@ class VertexBuffer11 : public VertexBuffer unsigned int offset, const uint8_t *sourceData) override; - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; + unsigned int getBufferSize() const override; + gl::Error setBufferSize(unsigned int size) override; + gl::Error discard() override; - virtual unsigned int getBufferSize() const; - virtual gl::Error setBufferSize(unsigned int size); - virtual gl::Error discard(); + void hintUnmapResource() override; - virtual void hintUnmapResource(); - - ID3D11Buffer *getBuffer() const; + const d3d11::Buffer &getBuffer() const; private: + ~VertexBuffer11() override; gl::Error mapResource(); Renderer11 *const mRenderer; - ID3D11Buffer *mBuffer; + d3d11::Buffer mBuffer; unsigned int mBufferSize; bool mDynamicUsage; uint8_t *mMappedResourceData; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl index 1ec21dee55..7c5c157c6f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -15,33 +15,42 @@ inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t cou if (attribSize == stride && inputComponentCount == outputComponentCount) { memcpy(output, input, count * attribSize); + return; } - else - { - const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); - const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + 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; - for (size_t j = 0; j < inputComponentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } + memcpy(offsetOutput, offsetInput, attribSize); + } + return; + } - for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) - { - // Set the remaining G/B channels to 0. - offsetOutput[j] = 0; - } + const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); - if (inputComponentCount < outputComponentCount && outputComponentCount == 4) - { - // Set the remaining alpha channel to the defaultAlphaValue. - offsetOutput[3] = defaultAlphaValue; - } + 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; } } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json new file mode 100644 index 0000000000..891d30d252 --- /dev/null +++ b/src/3rdparty/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": "BC1_RGBA_UNORM_SRGB_BLOCK", + "BC2_TYPELESS": "", + "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK", + "BC2_UNORM_SRGB": "BC2_RGBA_UNORM_SRGB_BLOCK", + "BC3_TYPELESS": "", + "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK", + "BC3_UNORM_SRGB": "BC3_RGBA_UNORM_SRGB_BLOCK", + "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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp new file mode 100644 index 0000000000..b0697bc5db --- /dev/null +++ b/src/3rdparty/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 2017 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: + return Format::Get(Format::ID::B8G8R8A8_UNORM_SRGB); + 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: + return Format::Get(Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK); + 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: + return Format::Get(Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK); + 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: + return Format::Get(Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK); + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json index e81b4deea5..942745674f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json @@ -8,7 +8,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_TYPELESS": { @@ -18,7 +19,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_FLOAT": { @@ -28,27 +30,30 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R32G32B32A32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_TYPELESS": { @@ -58,7 +63,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_FLOAT": { @@ -68,7 +74,8 @@ "shaderSample": "11_0check", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_UINT": { @@ -78,7 +85,8 @@ "shaderSample": "never", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_SINT": { @@ -88,7 +96,8 @@ "shaderSample": "never", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_TYPELESS": { @@ -98,57 +107,63 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_FLOAT": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "9_3check_10_0always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16B16A16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16B16A16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16G16B16A16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_TYPELESS": { @@ -158,7 +173,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_FLOAT": { @@ -168,37 +184,41 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R32G32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G8X24_TYPELESS": { - "texture2D": "always", + "texture2D": "10_0", "texture3D": "never", - "textureCube": "always", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D32_FLOAT_S8X24_UINT": { @@ -208,7 +228,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "10_0", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS": { @@ -218,7 +239,8 @@ "shaderSample": "10_0check10_1always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT": { @@ -228,47 +250,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10A2_TYPELESS": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10A2_UNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R10G10B10A2_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R11G11B10_FLOAT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8B8A8_TYPELESS": { @@ -278,57 +305,63 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8B8A8_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R8G8B8A8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8B8A8_SNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8B8A8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_TYPELESS": { @@ -338,7 +371,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_FLOAT": { @@ -348,57 +382,63 @@ "shaderSample": "10_0", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_SNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16G16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_TYPELESS": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D32_FLOAT": { @@ -408,7 +448,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "10_0", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_FLOAT": { @@ -418,27 +459,30 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R24G8_TYPELESS": { @@ -448,7 +492,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D24_UNORM_S8_UINT": { @@ -468,7 +513,8 @@ "shaderSample": "10_0check10_1always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_X24_TYPELESS_G8_UINT": { @@ -478,7 +524,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_TYPELESS": { @@ -488,47 +535,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_UNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "9_3check_10_0always", + "renderTarget": "9_3check_10_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_SNORM": { "texture2D": "always", - "texture3D": "always", - "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_TYPELESS": { @@ -538,17 +590,19 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_FLOAT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_D16_UNORM": { @@ -558,47 +612,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "always", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "shaderSample": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_TYPELESS": { @@ -608,47 +667,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "shaderSample": "always", + "renderTarget": "9_3check_10_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_A8_UNORM": { @@ -658,7 +722,8 @@ "shaderSample": "10_0", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R1_UNORM": { @@ -668,17 +733,19 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R9G9B9E5_SHAREDEXP": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_B8G8_UNORM": { @@ -688,7 +755,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_G8R8_G8B8_UNORM": { @@ -698,7 +766,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_TYPELESS": { @@ -708,27 +777,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_TYPELESS": { @@ -738,27 +810,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_TYPELESS": { @@ -768,27 +843,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_TYPELESS": { @@ -798,7 +876,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_UNORM": { @@ -808,7 +887,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_SNORM": { @@ -818,7 +898,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_TYPELESS": { @@ -828,7 +909,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_UNORM": { @@ -838,7 +920,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_SNORM": { @@ -848,7 +931,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B5G6R5_UNORM": { @@ -858,7 +942,8 @@ "shaderSample": "dxgi1_2", "renderTarget": "dxgi1_2", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" }, "DXGI_FORMAT_B5G5R5A1_UNORM": { @@ -868,17 +953,19 @@ "shaderSample": "dxgi1_2", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" }, "DXGI_FORMAT_B8G8R8A8_UNORM": { "texture2D": "check", "texture3D": "check", "textureCube": "check", - "shaderSample": "10_0check11_0always", - "renderTarget": "10_0check11_0always", + "shaderSample": "9_3always_10_0check11_0always", + "renderTarget": "9_3always_10_0check11_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_B8G8R8X8_UNORM": { @@ -888,7 +975,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM": { @@ -898,7 +986,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8A8_TYPELESS": { @@ -908,7 +997,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB": { @@ -918,7 +1008,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8X8_TYPELESS": { @@ -928,7 +1019,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB": { @@ -938,7 +1030,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_TYPELESS": { @@ -948,7 +1041,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_UF16": { @@ -958,7 +1052,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_SF16": { @@ -968,7 +1063,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_TYPELESS": { @@ -978,7 +1074,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_UNORM": { @@ -988,7 +1085,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_UNORM_SRGB": { @@ -998,7 +1096,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_AYUV": { @@ -1008,7 +1107,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y410": { @@ -1018,7 +1118,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y416": { @@ -1028,7 +1129,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_NV12": { @@ -1038,7 +1140,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P010": { @@ -1048,7 +1151,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P016": { @@ -1058,7 +1162,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_420_OPAQUE": { @@ -1068,7 +1173,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_YUY2": { @@ -1078,7 +1184,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y210": { @@ -1088,7 +1195,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y216": { @@ -1098,7 +1206,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_NV11": { @@ -1108,7 +1217,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_AI44": { @@ -1118,7 +1228,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_IA44": { @@ -1128,7 +1239,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P8": { @@ -1138,7 +1250,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_A8P8": { @@ -1148,7 +1261,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B4G4R4A4_UNORM": { @@ -1158,7 +1272,8 @@ "shaderSample": "dxgi1_2", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" } } ] diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp index cbc36445e6..4d7e46bdf2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp @@ -26,205 +26,205 @@ namespace d3d11 #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; + 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_10_0(DXGI_FORMAT dxgiFormat) +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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_B4G4R4A4_UNORM: { - static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + 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_SAMPLE, F_DS, F_MS | F_RT); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_SAMPLE, F_DS | F_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_RT | F_SAMPLE, F_MS); + 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: @@ -234,112 +234,112 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + 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_DS, F_3D | F_RT | F_SAMPLE, F_MS); + 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_SAMPLE, F_DS | F_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_NV12: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P010: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P016: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P8: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_R16G16_SNORM: @@ -349,157 +349,157 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_R16G16_TYPELESS: { - static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + static const DXGISupport info(0, 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_SAMPLE, F_MS); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, F_SAMPLE); + 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_RT, F_DS, F_MS | F_SAMPLE); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT); + 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_SAMPLE, F_MS | F_RT); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS | F_RT); + 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 | F_SAMPLE); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + 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_RT, F_DS, F_MS | F_SAMPLE); + 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_MS | F_RT, F_SAMPLE); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, 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_SAMPLE, F_MS); + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_R8G8B8A8_SNORM: @@ -509,122 +509,122 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_R8G8B8A8_TYPELESS: { - static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + 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_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_DS, F_MS); + static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE); return info; } case DXGI_FORMAT_R8_SINT: { - static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y216: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y410: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y416: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_YUY2: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -632,190 +632,192 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) UNREACHABLE(); return GetDefaultSupport(); } + // clang-format on } -const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) +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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_B4G4R4A4_UNORM: { - static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + 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_SAMPLE, F_DS, F_MS | F_RT); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_RT | F_SAMPLE, F_MS); + 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: @@ -825,397 +827,990 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + 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_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_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, 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_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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_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_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_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_3D | F_CUBE | F_DS | F_MIPGEN, 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_NV12: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P010: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P016: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P8: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT); + 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_SAMPLE, F_MS | F_RT); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS | F_RT); + 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_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y216: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y410: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y416: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_YUY2: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -1223,190 +1818,192 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(0, 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_RT | F_SAMPLE, F_MS); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_B4G4R4A4_UNORM: { - static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + 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_SAMPLE, F_DS, F_MS | F_RT); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + 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_2D | F_3D | F_CUBE | F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + 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_2D | F_3D | F_CUBE | F_MS); + 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_2D | F_3D | F_CUBE | F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_MS | F_RT, 0); + 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_RT | F_SAMPLE, F_MS); + 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: @@ -1416,397 +2013,990 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + 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_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_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, 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_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + 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_A8P8: + { + 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_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(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(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_NV11: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_NV12: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P010: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P016: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); return info; } case DXGI_FORMAT_P8: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + 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_TYPELESS: { - static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, F_2D | F_3D); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT, 0); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT); + 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_SAMPLE, F_MS | F_RT); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS | F_RT); + 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_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_SAMPLE, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT | F_SAMPLE, 0); + 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_SAMPLE, F_MS); + 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_RT | F_SAMPLE, F_DS, F_MS); + 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_MS | F_RT, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + 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_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y216: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y410: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_Y416: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_YUY2: { - static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -1814,6 +3004,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) UNREACHABLE(); return GetDefaultSupport(); } + // clang-format on } } @@ -1825,17 +3016,22 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) #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); + case D3D_FEATURE_LEVEL_11_1: + return GetDXGISupport_11_1(dxgiFormat); default: return GetDefaultSupport(); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h index 1d8d68565e..a818f376ef 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h @@ -8,6 +8,9 @@ // version, D3D feature level, and is sometimes guaranteed or optional. // +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ + #include "common/platform.h" namespace rx @@ -42,3 +45,5 @@ const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL feat } // namespace d3d11 } // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp index f073e9f46f..ce4edd26db 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -9,14 +9,15 @@ #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/copyimage.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" -#include "libANGLE/renderer/d3d/generatemip.h" -#include "libANGLE/renderer/d3d/loadimage.h" -#include "libANGLE/renderer/Renderer.h" namespace rx { @@ -24,559 +25,388 @@ namespace rx namespace d3d11 { -typedef std::map<DXGI_FORMAT, GLenum> DXGIToESFormatMap; - -inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) { - map->insert(std::make_pair(key, value)); + const auto &support = GetDXGISupport(dxgiFormat, featureLevel); + ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0); + return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0); } -static DXGIToESFormatMap BuildDXGIToESFormatMap() +DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight) + : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight) { - DXGIToESFormatMap map; - - AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); - - AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); - AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - - AddDXGIToESEntry(&map, DXGI_FORMAT_B5G6R5_UNORM, GL_RGB565); - AddDXGIToESEntry(&map, DXGI_FORMAT_B5G5R5A1_UNORM, GL_RGB5_A1); - AddDXGIToESEntry(&map, DXGI_FORMAT_B4G4R4A4_UNORM, GL_RGBA4); - - return map; } -struct D3D11FastCopyFormat +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format) { - GLenum destFormat; - GLenum destType; - ColorCopyFunction copyFunction; - - D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) - : destFormat(destFormat), destType(destType), copyFunction(copyFunction) - { } - - bool operator<(const D3D11FastCopyFormat& other) const + 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) { - return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; + 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; } -}; - -typedef std::multimap<DXGI_FORMAT, D3D11FastCopyFormat> D3D11FastCopyMap; - -static D3D11FastCopyMap BuildFastCopyMap() -{ - D3D11FastCopyMap map; - - map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); - - return map; -} - -struct DXGIColorFormatInfo -{ - size_t redBits; - size_t greenBits; - size_t blueBits; - - size_t luminanceBits; - - size_t alphaBits; - size_t sharedBits; -}; - -typedef std::map<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoMap; -typedef std::pair<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoPair; - -static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits, - size_t blueBits, size_t alphaBits, size_t sharedBits) -{ - DXGIColorFormatInfo info; - info.redBits = redBits; - info.greenBits = greenBits; - info.blueBits = blueBits; - info.alphaBits = alphaBits; - info.sharedBits = sharedBits; - - map->insert(std::make_pair(format, info)); -} - -static ColorFormatInfoMap BuildColorFormatInfoMap() -{ - ColorFormatInfoMap map; - - // | DXGI format | R | G | B | A | S | - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G6R5_UNORM, 5, 6, 5, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 4, 4, 4, 4, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 5, 5, 5, 1, 0); - - return map; -} - -struct DXGIDepthStencilInfo -{ - unsigned int depthBits; - unsigned int depthOffset; - unsigned int stencilBits; - unsigned int stencilOffset; -}; - -typedef std::map<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoMap; -typedef std::pair<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoPair; - -static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits, - unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) -{ - DXGIDepthStencilInfo info; - info.depthBits = depthBits; - info.depthOffset = depthOffset; - info.stencilBits = stencilBits; - info.stencilOffset = stencilOffset; - - map->insert(std::make_pair(format, info)); } -static DepthStencilInfoMap BuildDepthStencilInfoMap() +constexpr VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(nullptr) { - DepthStencilInfoMap map; - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32); - - return map; -} - -typedef std::map<DXGI_FORMAT, DXGIFormat> DXGIFormatInfoMap; - -DXGIFormat::DXGIFormat() - : pixelBytes(0), - blockWidth(0), - blockHeight(0), - redBits(0), - greenBits(0), - blueBits(0), - alphaBits(0), - sharedBits(0), - depthBits(0), - depthOffset(0), - stencilBits(0), - stencilOffset(0), - internalFormat(GL_NONE), - componentType(GL_NONE), - mipGenerationFunction(NULL), - colorReadFunction(NULL), - fastCopyFunctions(), - nativeMipmapSupport(NULL) -{ -} - -static bool NeverSupported(D3D_FEATURE_LEVEL) -{ - return false; -} - -template <D3D_FEATURE_LEVEL requiredFeatureLevel> -static bool RequiresFeatureLevel(D3D_FEATURE_LEVEL featureLevel) -{ - return featureLevel >= requiredFeatureLevel; } -ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const +constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, + DXGI_FORMAT nativeFormatIn, + VertexCopyFunction copyFunctionIn) + : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn) { - FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); - return (iter != fastCopyFunctions.end()) ? iter->second : NULL; } -void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc, NativeMipmapGenerationSupportFunction nativeMipmapSupport) +const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType) { - DXGIFormat info; - info.pixelBytes = pixelBits / 8; - info.blockWidth = blockWidth; - info.blockHeight = blockHeight; - - static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap(); - ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat); - if (colorInfoIter != colorInfoMap.end()) - { - const DXGIColorFormatInfo &colorInfo = colorInfoIter->second; - info.redBits = static_cast<GLuint>(colorInfo.redBits); - info.greenBits = static_cast<GLuint>(colorInfo.greenBits); - info.blueBits = static_cast<GLuint>(colorInfo.blueBits); - info.alphaBits = static_cast<GLuint>(colorInfo.alphaBits); - info.sharedBits = static_cast<GLuint>(colorInfo.sharedBits); - } - - static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); - DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); - if (dsInfoIter != dsInfoMap.end()) - { - const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second; - info.depthBits = dsInfo.depthBits; - info.depthOffset = dsInfo.depthOffset; - info.stencilBits = dsInfo.stencilBits; - info.stencilOffset = dsInfo.stencilOffset; - } - - static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); - DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); - info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; - - info.componentType = componentType; - - info.mipGenerationFunction = mipFunc; - info.colorReadFunction = readFunc; + // 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 - static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); - std::pair<D3D11FastCopyMap::const_iterator, D3D11FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(dxgiFormat); - for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + switch (vertexFormatType) { - info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); - } - - info.nativeMipmapSupport = nativeMipmapSupport; - - map->insert(std::make_pair(dxgiFormat, info)); -} - -// A map to determine the pixel size and mipmap generation function of a given DXGI format -static DXGIFormatInfoMap BuildDXGIFormatInfoMap() -{ - DXGIFormatInfoMap map; - - // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function | Native mipmap function - AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL, NeverSupported); - - AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A8>, ReadColor<A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8>, ReadColor<R8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8>, ReadColor<R8G8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>); - AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8S>, ReadColor<R8S, GLfloat> , RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8S>, ReadColor<R8G8S, GLfloat> , RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8>, ReadColor<R8, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16>, ReadColor<R16, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32>, ReadColor<R32, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8>, ReadColor<R8G8, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16>, ReadColor<R16G16, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32>, ReadColor<R32G32, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32>, ReadColor<R32G32B32, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16B16A16>, ReadColor<R16G16B16A16, GLuint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32A32>, ReadColor<R32G32B32A32, GLuint>, NeverSupported); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip<R8S>, ReadColor<R8S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip<R16S>, ReadColor<R16S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip<R32S>, ReadColor<R32S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip<R8G8S>, ReadColor<R8G8S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip<R16G16S>, ReadColor<R16G16S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip<R32G32S>, ReadColor<R32G32S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip<R32G32B32S>, ReadColor<R32G32B32S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip<R16G16B16A16S>, ReadColor<R16G16B16A16S, GLint>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip<R32G32B32A32S>, ReadColor<R32G32B32A32S, GLint>, NeverSupported); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLuint>, NeverSupported); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip<R16F>, ReadColor<R16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>); + // GL_UNSIGNED_BYTE -- normalized + // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R32F>, ReadColor<R32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_3>); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip<R9G9B9E5>, ReadColor<R9G9B9E5, GLfloat>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R11G11B10F>, ReadColor<R11G11B10F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported); + // 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; + } - AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + // 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; + } - // B5G6R5 in D3D11 is treated the same as R5G6B5 in D3D9, so reuse the R5G6B5 functions used by the D3D9 renderer. - // The same applies to B4G4R4A4 and B5G5R5A1 with A4R4G4B4 and A1R5G5B5 respectively. - AddDXGIFormat(&map, DXGI_FORMAT_B5G6R5_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>); - AddDXGIFormat(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A4R4G4B4>, ReadColor<A4R4G4B4, GLfloat>, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A1R5G5B5>, ReadColor<A1R5G5B5, GLfloat>, NeverSupported); + // 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; + } - // Useful formats for vertex buffers - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); + // 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; + } - return map; -} + // 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; + } -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) -{ - static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); - DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second; - } - else - { - static DXGIFormat defaultInfo; - return defaultInfo; + default: + return nullptr; } } -typedef std::map<gl::VertexFormatType, VertexFormat> D3D11VertexFormatInfoMap; -typedef std::pair<gl::VertexFormatType, VertexFormat> D3D11VertexFormatPair; - -VertexFormat::VertexFormat() - : conversionType(VERTEX_CONVERT_NONE), - nativeFormat(DXGI_FORMAT_UNKNOWN), - copyFunction(NULL) -{ -} - -VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, - DXGI_FORMAT nativeFormatIn, - VertexCopyFunction copyFunctionIn) - : conversionType(conversionTypeIn), - nativeFormat(nativeFormatIn), - copyFunction(copyFunctionIn) -{ -} - -static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, - GLenum inputType, - GLboolean normalized, - GLuint componentCount, - VertexConversionType conversionType, - DXGI_FORMAT nativeFormat, - VertexCopyFunction copyFunction) -{ - gl::VertexFormatType formatType = gl::GetVertexFormatType(inputType, normalized, componentCount, false); - - VertexFormat info; - info.conversionType = conversionType; - info.nativeFormat = nativeFormat; - info.copyFunction = copyFunction; - - map->insert(D3D11VertexFormatPair(formatType, info)); -} - -static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() -{ - // 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 - - D3D11VertexFormatInfoMap map; - - // GL_BYTE -- unnormalized - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>); - - // GL_BYTE -- normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>); - - // GL_UNSIGNED_BYTE -- unnormalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 1, 4, 1>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 2, 4, 1>); - // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table. - - // GL_UNSIGNED_BYTE -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>); - // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. - - // GL_SHORT -- unnormalized - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 1, 2, 0>); - // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. - - // GL_SHORT -- normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 1, 2, 0>); - // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. - - // GL_UNSIGNED_SHORT -- unnormalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, false>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, false>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, false>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, false>); - - // GL_UNSIGNED_SHORT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, true>); - - // GL_FIXED - // TODO: Add test to verify that this works correctly. - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>); - // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. - - // GL_FLOAT - // TODO: Add test to verify that this works correctly. - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 2, 0>); - // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. - - return map; -} - const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel) { if (featureLevel == D3D_FEATURE_LEVEL_9_3) { - static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = - BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); - - // First see if the format has a special mapping for FL9_3 - auto iter = vertexFormatMapFL9_3Override.find(vertexFormatType); - if (iter != vertexFormatMapFL9_3Override.end()) + const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType); + if (result) { - return iter->second; + return *result; } } @@ -589,354 +419,418 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D // GL_BYTE -- un-normalized case gl::VERTEX_FORMAT_SBYTE1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, + &CopyNativeVertexData<GLbyte, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_SBYTE2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, + &CopyNativeVertexData<GLbyte, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_SBYTE3: { - static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>); + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData<GLbyte, 3, 4, 1>); return info; } case gl::VERTEX_FORMAT_SBYTE4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, + &CopyNativeVertexData<GLubyte, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_UBYTE2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, + &CopyNativeVertexData<GLubyte, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_UBYTE3: { - static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>); + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData<GLubyte, 3, 4, 1>); return info; } case gl::VERTEX_FORMAT_UBYTE4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, + &CopyNativeVertexData<GLshort, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_SSHORT2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, + &CopyNativeVertexData<GLshort, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_SSHORT3: { - static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>); + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData<GLshort, 3, 4, 1>); return info; } case gl::VERTEX_FORMAT_SSHORT4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, + &CopyNativeVertexData<GLushort, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_USHORT2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, + &CopyNativeVertexData<GLushort, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_USHORT3: { - static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>); + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData<GLushort, 3, 4, 1>); return info; } case gl::VERTEX_FORMAT_USHORT4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, + &CopyNativeVertexData<GLint, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_SINT2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, + &CopyNativeVertexData<GLint, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_SINT3: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, + &CopyNativeVertexData<GLint, 3, 3, 0>); return info; } case gl::VERTEX_FORMAT_SINT4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, 1, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, 2, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, 3, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, 4, true>); + 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 const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, + &CopyNativeVertexData<GLuint, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_UINT2: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, + &CopyNativeVertexData<GLuint, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_UINT3: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 3, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, + &CopyNativeVertexData<GLuint, 3, 3, 0>); return info; } case gl::VERTEX_FORMAT_UINT4: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, 1, true>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, 2, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, 3, true>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, 4, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, + &Copy32FixedTo32FVertexData<1, 1>); return info; } case gl::VERTEX_FORMAT_FIXED2: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &Copy32FixedTo32FVertexData<2, 2>); return info; } case gl::VERTEX_FORMAT_FIXED3: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &Copy32FixedTo32FVertexData<3, 3>); return info; } case gl::VERTEX_FORMAT_FIXED4: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, + &CopyNativeVertexData<GLhalf, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_HALF2: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, + &CopyNativeVertexData<GLhalf, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_HALF3: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, + &CopyNativeVertexData<GLfloat, 1, 1, 0>); return info; } case gl::VERTEX_FORMAT_FLOAT2: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 2, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, + &CopyNativeVertexData<GLfloat, 2, 2, 0>); return info; } case gl::VERTEX_FORMAT_FLOAT3: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 3, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyNativeVertexData<GLfloat, 3, 3, 0>); return info; } case gl::VERTEX_FORMAT_FLOAT4: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>); return info; } case gl::VERTEX_FORMAT_SINT210_NORM: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>); return info; } case gl::VERTEX_FORMAT_UINT210_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, + &CopyNativeVertexData<GLuint, 1, 1, 0>); return info; } @@ -947,157 +841,183 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D // GL_BYTE case gl::VERTEX_FORMAT_SBYTE1_INT: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 2, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 3, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 4, 0>); + 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 const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>); + 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 const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, + &CopyNativeVertexData<GLuint, 1, 1, 0>); return info; } default: { - static const VertexFormat info; + static constexpr VertexFormat info; return info; } } } -} +} // namespace d3d11 -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h index 7b97527140..883d338377 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -15,6 +15,7 @@ #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 @@ -24,58 +25,47 @@ struct Renderer11DeviceCaps; namespace d3d11 { -typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap; -typedef bool (*NativeMipmapGenerationSupportFunction)(D3D_FEATURE_LEVEL); +// 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. -struct DXGIFormat +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel); + +struct DXGIFormatSize { - DXGIFormat(); + DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight); GLuint pixelBytes; GLuint blockWidth; GLuint blockHeight; - - GLuint redBits; - GLuint greenBits; - GLuint blueBits; - GLuint alphaBits; - GLuint sharedBits; - - GLuint depthBits; - GLuint depthOffset; - GLuint stencilBits; - GLuint stencilOffset; - - GLenum internalFormat; - GLenum componentType; - - MipGenerationFunction mipGenerationFunction; - ColorReadFunction colorReadFunction; - - FastCopyFunctionMap fastCopyFunctions; - - NativeMipmapGenerationSupportFunction nativeMipmapSupport; - - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; }; -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format); -struct VertexFormat +struct VertexFormat : private angle::NonCopyable { - VertexFormat(); - VertexFormat(VertexConversionType conversionType, - DXGI_FORMAT nativeFormat, - VertexCopyFunction copyFunction); + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp deleted file mode 100644 index e69de29bb2..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp +++ /dev/null diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp deleted file mode 100644 index adb20a5e60..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// 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. -// -// internal_format_initializer_table: -// Contains table to go from internal format and dxgi format to initializer function -// for TextureFormat -// - -#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h" -#include "libANGLE/renderer/d3d/loadimage.h" - -namespace rx -{ - -namespace d3d11 -{ - -// TODO: This should be generated by a JSON file -InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat, - DXGI_FORMAT dxgiFormat) -{ - switch (internalFormat) - { - case GL_RGB8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>; - } - default: - break; - } - } - case GL_RGB565: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>; - } - default: - break; - } - } - case GL_SRGB8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>; - } - default: - break; - } - } - case GL_RGB16F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - return Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>; - } - default: - break; - } - } - case GL_RGB32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - return Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, - gl::Float32One>; - } - default: - break; - } - } - case GL_RGB8UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UINT: - { - return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>; - } - default: - break; - } - } - case GL_RGB8I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_SINT: - { - return Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>; - } - default: - break; - } - } - case GL_RGB16UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_UINT: - { - return Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>; - } - default: - break; - } - } - case GL_RGB16I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_SINT: - { - return Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>; - } - default: - break; - } - } - case GL_RGB32UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_UINT: - { - return Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, - 0x00000001>; - } - default: - break; - } - } - case GL_RGB32I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_SINT: - { - return Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, - 0x00000001>; - } - default: - break; - } - } - default: - { - return nullptr; - } - } -} - -} // namespace d3d11 - -} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h deleted file mode 100644 index 2d538e1d82..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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. -// -// internal_format_initializer_table: -// Contains table to go from internal format and dxgi format to initializer function -// for TextureFormat -// - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ - -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" - -#include <map> - -namespace rx -{ - -namespace d3d11 -{ - -InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat, - DXGI_FORMAT dxgiFormat); - -} // namespace d3d11 - -} // namespace rx - -#endif // LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json deleted file mode 100644 index c85393e06b..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json +++ /dev/null @@ -1,1116 +0,0 @@ -{ - "GL_RG8_SNORM": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,2>", - "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM", - "requiresConversion": "false" - } - ] - }, - "GL_SRGB8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLubyte,0xFF>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA8I": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_R8_SNORM": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,1>", - "dxgiFormat": "DXGI_FORMAT_R8_SNORM", - "requiresConversion": "false" - } - ] - }, - "GL_RGBA8_SNORM": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "requiresConversion": "false" - } - ] - }, - "GL_R16I": { - "GL_SHORT": [ - { - "loadFunction": "LoadToNative<GLshort,1>", - "dxgiFormat": "DXGI_FORMAT_R16_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2SRGBA8ToSRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2RGB8A1ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGB32UI": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadToNative3To4<GLuint,0x00000001>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "requiresConversion": "true" - } - ] - }, - "GL_ALPHA32F_EXT": { - "GL_FLOAT": [ - { - "loadFunction": "LoadA32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_R16UI": { - "GL_UNSIGNED_SHORT": [ - { - "loadFunction": "LoadToNative<GLushort,1>", - "dxgiFormat": "DXGI_FORMAT_R16_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_RGB9_E5": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadRGB16FToRGB9E5", - "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_INT_5_9_9_9_REV": [ - { - "loadFunction": "LoadToNative<GLuint,1>", - "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", - "requiresConversion": "false" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadRGB32FToRGB9E5", - "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadRGB16FToRGB9E5", - "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_R11_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadEACR11ToR8", - "dxgiFormat": "DXGI_FORMAT_R8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA32UI": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadToNative<GLuint,4>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_RG8UI": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,2>", - "dxgiFormat": "DXGI_FORMAT_R8G8_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE32F_EXT": { - "GL_FLOAT": [ - { - "loadFunction": "LoadL32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2SRGB8A1ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requiresConversion": "true" - } - ] - }, - "GL_R16F": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadToNative<GLhalf,1>", - "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", - "requiresConversion": "false" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "Load32FTo16F<1>", - "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadToNative<GLhalf,1>", - "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_RGBA8UI": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_BGRA4_ANGLEX": { - "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": [ - { - "loadFunction": "LoadRGBA4ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "false" - } - ] - }, - "GL_RGBA16F": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadToNative<GLhalf,4>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "false" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "Load32FTo16F<4>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadToNative<GLhalf,4>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE8_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadL8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadCompressedToNative<4,4,16>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RGB": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_SHORT_5_6_5": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RGB5_A1": { - "GL_UNSIGNED_INT_2_10_10_10_REV": [ - { - "loadFunction": "LoadRGB10A2ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "false" - } - ], - "GL_UNSIGNED_SHORT_5_5_5_1": [ - { - "loadFunction": "LoadRGB5A1ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - }, - { - "loadFunction": "LoadRGB5A1ToA1RGB5", - "dxgiFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGB16UI": { - "GL_UNSIGNED_SHORT": [ - { - "loadFunction": "LoadToNative3To4<GLushort,0x0001>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "requiresConversion": "true" - } - ] - }, - "GL_BGRA_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RGB8_ETC2": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2RGB8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA32F": { - "GL_FLOAT": [ - { - "loadFunction": "LoadToNative<GLfloat,4>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_RGBA32I": { - "GL_INT": [ - { - "loadFunction": "LoadToNative<GLint,4>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE8_ALPHA8_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadLA8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RG8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,2>", - "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_RGB10_A2": { - "GL_UNSIGNED_INT_2_10_10_10_REV": [ - { - "loadFunction": "LoadToNative<GLuint,1>", - "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_COMPRESSED_SIGNED_RG11_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadEACRG11SToRG8", - "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM", - "requiresConversion": "true" - } - ] - }, - "GL_DEPTH_COMPONENT16": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadR32ToR16", - "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_SHORT": [ - { - "loadFunction": "LoadToNative<GLushort,1>", - "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS", - "requiresConversion": "false" - }, - { - "loadFunction": "LoadToNative<GLushort,1>", - "dxgiFormat": "DXGI_FORMAT_D16_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_RGB32I": { - "GL_INT": [ - { - "loadFunction": "LoadToNative3To4<GLint,0x00000001>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "requiresConversion": "true" - } - ] - }, - "GL_R8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,1>", - "dxgiFormat": "DXGI_FORMAT_R8_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_RGB32F": { - "GL_FLOAT": [ - { - "loadFunction": "LoadToNative3To4<GLfloat,gl::Float32One>", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_R11F_G11F_B10F": { - "GL_UNSIGNED_INT_10F_11F_11F_REV": [ - { - "loadFunction": "LoadToNative<GLuint,1>", - "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "requiresConversion": "false" - } - ], - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadRGB16FToRG11B10F", - "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "requiresConversion": "true" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadRGB32FToRG11B10F", - "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadRGB16FToRG11B10F", - "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_RGB8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLubyte,0xFF>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_LUMINANCE_ALPHA": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadLA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadLA32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadLA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA16I": { - "GL_SHORT": [ - { - "loadFunction": "LoadToNative<GLshort,4>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_R8I": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,1>", - "dxgiFormat": "DXGI_FORMAT_R8_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_RGB8_SNORM": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLbyte,0x7F>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RG32F": { - "GL_FLOAT": [ - { - "loadFunction": "LoadToNative<GLfloat,2>", - "dxgiFormat": "DXGI_FORMAT_R32G32_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_DEPTH_COMPONENT32F": { - "GL_FLOAT": [ - { - "loadFunction": "LoadToNative<GLfloat,1>", - "dxgiFormat": "DXGI_FORMAT_R32_TYPELESS", - "requiresConversion": "false" - }, - { - "loadFunction": "UnimplementedLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RG32I": { - "GL_INT": [ - { - "loadFunction": "LoadToNative<GLint,2>", - "dxgiFormat": "DXGI_FORMAT_R32G32_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_ALPHA8_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,1>", - "dxgiFormat": "DXGI_FORMAT_A8_UNORM", - "requiresConversion": "false" - }, - { - "loadFunction": "LoadA8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RG32UI": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadToNative<GLuint,2>", - "dxgiFormat": "DXGI_FORMAT_R32G32_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_RGBA16UI": { - "GL_UNSIGNED_SHORT": [ - { - "loadFunction": "LoadToNative<GLushort,4>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_COMPRESSED_RGBA8_ETC2_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2RGBA8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGB8I": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLbyte,0x01>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_SRGB8_ETC2": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC2SRGB8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requiresConversion": "true" - } - ] - }, - "GL_DEPTH32F_STENCIL8": { - "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": [ - { - "loadFunction": "LoadToNative<GLuint,2>", - "dxgiFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", - "requiresConversion": "false" - }, - { - "loadFunction": "UnimplementedLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RG8I": { - "GL_BYTE": [ - { - "loadFunction": "LoadToNative<GLbyte,2>", - "dxgiFormat": "DXGI_FORMAT_R8G8_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_R32UI": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadToNative<GLuint,1>", - "dxgiFormat": "DXGI_FORMAT_R32_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_BGR5_A1_ANGLEX": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "false" - } - ], - "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": [ - { - "loadFunction": "LoadRGB5A1ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RG11_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadEACRG11ToRG8", - "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_SRGB8_ALPHA8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE_ALPHA16F_EXT": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadLA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadLA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_SHORT_4_4_4_4": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_SHORT_5_5_5_1": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_DEPTH24_STENCIL8": { - "GL_UNSIGNED_INT_24_8": [ - { - "loadFunction": "LoadR32ToR24G8", - "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "requiresConversion": "true" - }, - { - "loadFunction": "LoadR32ToR24G8", - "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requiresConversion": "true" - } - ] - }, - "GL_RGB16I": { - "GL_SHORT": [ - { - "loadFunction": "LoadToNative3To4<GLshort,0x0001>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "requiresConversion": "true" - } - ] - }, - "GL_R8UI": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,1>", - "dxgiFormat": "DXGI_FORMAT_R8_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_ALPHA": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadA32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_RGB16F": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadRGB32FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_SIGNED_R11_EAC": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadEACR11SToR8", - "dxgiFormat": "DXGI_FORMAT_R8_SNORM", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadCompressedToNative<4,4,8>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadCompressedToNative<4,4,8>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_STENCIL_INDEX8": { - "DXGI_FORMAT_R24G8_TYPELESS": [ - { - "loadFunction": "UnimplementedLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "DXGI_FORMAT_D24_UNORM_S8_UINT": [ - { - "loadFunction": "UnimplementedLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_LUMINANCE_ALPHA32F_EXT": { - "GL_FLOAT": [ - { - "loadFunction": "LoadLA32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RGB8UI": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLubyte,0x01>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "requiresConversion": "true" - } - ] - }, - "GL_DEPTH_COMPONENT24": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadR32ToR24G8", - "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "requiresConversion": "true" - }, - { - "loadFunction": "LoadR32ToR24G8", - "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requiresConversion": "true" - } - ] - }, - "GL_R32I": { - "GL_INT": [ - { - "loadFunction": "LoadToNative<GLint,1>", - "dxgiFormat": "DXGI_FORMAT_R32_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_DEPTH_COMPONENT32_OES": { - "GL_UNSIGNED_INT": [ - { - "loadFunction": "LoadR32ToR24G8", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_R32F": { - "GL_FLOAT": [ - { - "loadFunction": "LoadToNative<GLfloat,1>", - "dxgiFormat": "DXGI_FORMAT_R32_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_RG16F": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadToNative<GLhalf,2>", - "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", - "requiresConversion": "false" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "Load32FTo16F<2>", - "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadToNative<GLhalf,2>", - "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", - "requiresConversion": "false" - } - ] - }, - "GL_RGB565": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative3To4<GLubyte,0xFF>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_SHORT_5_6_5": [ - { - "loadFunction": "LoadR5G6B5ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - }, - { - "loadFunction": "LoadToNative<GLushort,1>", - "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE16F_EXT": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadL16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadL16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RG16UI": { - "GL_UNSIGNED_SHORT": [ - { - "loadFunction": "LoadToNative<GLushort,2>", - "dxgiFormat": "DXGI_FORMAT_R16G16_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadCompressedToNative<4,4,16>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RG16I": { - "GL_SHORT": [ - { - "loadFunction": "LoadToNative<GLshort,2>", - "dxgiFormat": "DXGI_FORMAT_R16G16_SINT", - "requiresConversion": "false" - } - ] - }, - "GL_BGRA8_EXT": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "false" - } - ] - }, - "GL_ALPHA16F_EXT": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadA16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA4": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "false" - } - ], - "GL_UNSIGNED_SHORT_4_4_4_4": [ - { - "loadFunction": "LoadRGBA4ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - }, - { - "loadFunction": "LoadRGBA4ToARGB4", - "dxgiFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_RGBA8": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadToNative<GLubyte,4>", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "false" - } - ] - }, - "GL_LUMINANCE": { - "GL_HALF_FLOAT": [ - { - "loadFunction": "LoadL16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ], - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "UnreachableLoadFunction", - "dxgiFormat": "DXGI_FORMAT_UNKNOWN", - "requiresConversion": "true" - } - ], - "GL_FLOAT": [ - { - "loadFunction": "LoadL32FToRGBA32F", - "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "requiresConversion": "true" - } - ], - "GL_HALF_FLOAT_OES": [ - { - "loadFunction": "LoadL16FToRGBA16F", - "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "requiresConversion": "true" - } - ] - }, - "GL_RGB10_A2UI": { - "GL_UNSIGNED_INT_2_10_10_10_REV": [ - { - "loadFunction": "LoadToNative<GLuint,1>", - "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UINT", - "requiresConversion": "false" - } - ] - }, - "GL_ETC1_RGB8_OES": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC1RGB8ToRGBA8", - "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requiresConversion": "true" - } - ] - }, - "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": { - "GL_UNSIGNED_BYTE": [ - { - "loadFunction": "LoadETC1RGB8ToBC1", - "dxgiFormat": "DXGI_FORMAT_BC1_UNORM", - "requiresConversion": "true" - } - ] - } -}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h deleted file mode 100644 index b17062f68d..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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. -// -// load_functions_table: -// Contains load functions table depending on internal format and dxgi format -// - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ - -#include <map> - -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" - -namespace rx -{ - -namespace d3d11 -{ - -const std::map<GLenum, LoadImageFunctionInfo> &GetLoadFunctionsMap(GLenum internalFormat, - DXGI_FORMAT dxgiFormat); - -} // namespace d3d11 - -} // namespace rx - -#endif // LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp deleted file mode 100644 index acb48b9573..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp +++ /dev/null @@ -1,2098 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_load_functions_table.py using data from load_functions_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. -// -// load_functions_table: -// Contains the GetLoadFunctionsMap for texture_format_util.h -// - -#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" -#include "libANGLE/renderer/d3d/loadimage.h" -#include "libANGLE/renderer/d3d/loadimage_etc.h" - -namespace rx -{ - -namespace d3d11 -{ - -namespace -{ - -// ES3 image loading functions vary based on: -// - the GL internal format (supplied to glTex*Image*D) -// - the GL data type given (supplied to glTex*Image*D) -// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D -// device's capabilities) -// This map type determines which loading function to use, based on these three parameters. -// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec. -void UnimplementedLoadFunction(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) -{ - UNIMPLEMENTED(); -} - -void UnreachableLoadFunction(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(); -} - -} // namespace - -// TODO we can replace these maps with more generated code -const std::map<GLenum, LoadImageFunctionInfo> &GetLoadFunctionsMap(GLenum internalFormat, - DXGI_FORMAT dxgiFormat) -{ - // clang-format off - switch (internalFormat) - { - case GL_ALPHA: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_ALPHA16F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_ALPHA32F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_ALPHA8_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadA8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_BGR5_A1_ANGLEX: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true); - loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_BGRA4_ANGLEX: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true); - loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_BGRA8_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_BGRA_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_COMPRESSED_R11_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11ToR8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_RG11_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11ToRG8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_RGB8_ETC2: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_RGBA8_ETC2_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_COMPRESSED_SIGNED_R11_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11SToR8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_SIGNED_RG11_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11SToRG8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_SRGB8_ETC2: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_DEPTH24_STENCIL8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_D24_UNORM_S8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R24G8_TYPELESS: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_DEPTH32F_STENCIL8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G8X24_TYPELESS: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_DEPTH_COMPONENT16: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_D16_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R16_TYPELESS: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR16, true); - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_DEPTH_COMPONENT24: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_D24_UNORM_S8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R24G8_TYPELESS: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_DEPTH_COMPONENT32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32_TYPELESS: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_DEPTH_COMPONENT32_OES: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_BC1_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_ETC1_RGB8_OES: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_LUMINANCE: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE16F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE32F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE8_ALPHA8_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE8_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE_ALPHA: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE_ALPHA16F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_LUMINANCE_ALPHA32F_EXT: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_R11F_G11F_B10F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R11G11B10_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true); - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true); - loadMap[GL_UNSIGNED_INT_10F_11F_11F_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R16F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<1>, true); - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,1>, false); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R16I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R16UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R32I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R32UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R8I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R8UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_R8_SNORM: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG16F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<2>, true); - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,2>, false); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG16I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG16UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG32I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG32UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG8I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG8UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RG8_SNORM: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,2>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_RGB10_A2: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R10G10B10A2_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB10_A2UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R10G10B10A2_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB16F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true); - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4<GLhalf,gl::Float16One>, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative3To4<GLhalf,gl::Float16One>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB16I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative3To4<GLshort,0x0001>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB16UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative3To4<GLushort,0x0001>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4<GLfloat,gl::Float32One>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB32I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative3To4<GLint,0x00000001>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB32UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative3To4<GLuint,0x00000001>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB565: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_B5G6R5_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB5_A1: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_B5G5R5A1_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true); - loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB8I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLbyte,0x01>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB8UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0x01>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB8_SNORM: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLbyte,0x7F>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGB9_E5: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true); - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true); - loadMap[GL_UNSIGNED_INT_5_9_9_9_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - case GL_RGBA16F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<4>, true); - loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,4>, false); - loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA16I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA16UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R16G16B16A16_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA32F: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA32I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA32UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R32G32B32A32_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA4: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_B4G4R4A4_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToARGB4, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA8I: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_SINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA8UI: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UINT: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_RGBA8_SNORM: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_SNORM: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_SRGB8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_SRGB8_ALPHA8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - break; - } - } - case GL_STENCIL_INDEX8: - { - switch (dxgiFormat) - { - case DXGI_FORMAT_UNKNOWN: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - default: - { - static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() { - std::map<GLenum, LoadImageFunctionInfo> loadMap; - loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); - return loadMap; - }(); - - return loadFunctionsMap; - } - } - } - - default: - { - static std::map<GLenum, LoadImageFunctionInfo> emptyLoadFunctionsMap; - return emptyLoadFunctionsMap; - } - } - // clang-format on - -} // GetLoadFunctionsMap - -} // namespace d3d11 - -} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index a1175db9af..d059b36120 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -12,319 +12,52 @@ #include <algorithm> #include "common/debug.h" -#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.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" - -#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY -# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 -#endif -#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 -#endif -#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 -#endif -#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 -#endif -#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 -#endif -#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION -# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 -#endif -#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION -# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_SO_BUFFER_SLOT_COUNT -# define D3D11_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -#endif -#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT -# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 -#endif -#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -#endif -#ifndef D3D11_PS_INPUT_REGISTER_COUNT -# define D3D11_PS_INPUT_REGISTER_COUNT 32 -#endif -#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT -# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 -#endif -#if defined(ANGLE_MINGW32_COMPAT) -static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; -#endif +#include "libANGLE/renderer/driver_utils.h" +#include "platform/Platform.h" +#include "platform/WorkaroundsD3D.h" namespace rx { -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; -} - -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; - default: UNREACHABLE(); return D3D11_QUERY_EVENT; - } -} - -} // namespace gl_d3d11 - namespace d3d11_gl { - namespace { +// Standard D3D sample positions from +// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx +using SamplePositionsArray = std::array<float, 32>; +static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = { + {{{0.5f, 0.5f}}, + {{0.75f, 0.75f, 0.25f, 0.25f}}, + {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}}, + {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f, + 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}}, + {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f, + 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f, + 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f, + 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}}; // 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) + : mDevice(device), mFeatureLevel(featureLevel) { } @@ -347,7 +80,7 @@ class DXGISupportHelper : angle::NonCopyable else { // TODO(jmadill): find out why we fail this call sometimes in FL9_3 - // ERR("Error checking format support for format 0x%x", dxgiFormat); + // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat; } } @@ -359,93 +92,46 @@ class DXGISupportHelper : angle::NonCopyable D3D_FEATURE_LEVEL mFeatureLevel; }; -} // 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: - case D3D_FEATURE_LEVEL_10_0: return 3; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 2; - - default: UNREACHABLE(); return 0; - } -} - -static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps) +gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion, + GLenum internalFormat, + ID3D11Device *device, + const Renderer11DeviceCaps &renderer11DeviceCaps) { gl::TextureCaps textureCaps; DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel); - const d3d11::TextureFormat &formatInfo = - d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) { texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; - if (maxClientVersion > 2) + if (maxClientVersion.major > 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)); + 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)); - if (support.query(formatInfo.renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + 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); @@ -454,7 +140,8 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum sampleCount *= 2) { UINT qualityCount = 0; - if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount))) + if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount, + &qualityCount))) { // Assume we always support lower sample counts if (qualityCount == 0) @@ -469,691 +156,1124 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum return textureCaps; } -static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +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; + 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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return false; } } -static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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_3: + case D3D_FEATURE_LEVEL_9_2: + return 16; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +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; + 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; + // 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; + default: + UNREACHABLE(); + return false; } } -static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + // 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; + 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; + default: + UNREACHABLE(); + return false; } } -static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + // 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_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; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return false; } } -static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) +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_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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return false; } } -static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) +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_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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return false; } } -static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) { - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model + // 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 + // 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; + 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; + default: + UNREACHABLE(); + return false; } } -static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +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_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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return false; } } -static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + // 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_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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +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_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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + 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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + 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_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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +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_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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +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 + // 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."); + 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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +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 + // 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_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; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexUniformVectors(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_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 1024; // D3D10_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); + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetReservedVertexUniformBuffers() -{ - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +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 - GetReservedVertexUniformBuffers(); + 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 - GetReservedVertexUniformBuffers(); + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - // According to The OpenGL ES Shading Language specifications + // 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. + // 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; + // 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; + // 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; + default: + UNREACHABLE(); + return 0; } - - return 1; } -static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value."); + 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_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); + 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); + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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); + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetReservedPixelUniformBuffers() +size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; + 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; + } } -static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumPixelTextureUnits(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 - GetReservedPixelUniformBuffers(); + 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_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_SAMPLER_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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +std::array<GLuint, 3> GetMaxComputeWorkGroupCount(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_11_1: + case D3D_FEATURE_LEVEL_11_0: + return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, + D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, + D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}}; + break; + default: + return {{0, 0, 0}}; + } +} - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); +std::array<GLuint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y, + D3D11_CS_THREAD_GROUP_MAX_Z}}; + break; + default: + return {{0, 0, 0}}; + } +} - // 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); +size_t GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP; + default: + return 0; + } +} - default: UNREACHABLE(); return 0; +size_t GetMaximumComputeUniformVectors(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; + default: + return 0; } } -static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumComputeUniformBlocks(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_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + default: + return 0; + } +} - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; +size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + default: + return 0; + } +} - // 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; +size_t GetMaximumImageUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using + // the minimum requirement for GLES 3.1. + return 4; + default: + return 0; + } +} - default: UNREACHABLE(); return 0; +size_t GetMaximumComputeImageUniforms(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using + // the minimum requirement for GLES 3.1. + return 4; + default: + return 0; } } -static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +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_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; + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +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; + 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; + // 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +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 + // 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_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: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + 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; - // 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 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumStreamOutputSeparateComponents(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_11_1: + case D3D_FEATURE_LEVEL_11_0: + return GetMaximumStreamOutputInterleavedComponents(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); - 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; + // 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; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH; + + // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9, + // 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; } } -static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) +IntelDriverVersion GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion) +{ + if (!driverVersion.valid()) + return IntelDriverVersion(0); + + // According to http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html, + // only the fourth part is necessary since it stands for the driver specific unique version + // number. + WORD part = LOWORD(driverVersion.value().LowPart); + return IntelDriverVersion(part); +} + +} // 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_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_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 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; + 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) +gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / - GetMaximumStreamOutputBuffers(featureLevel); + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return gl::Version(3, 1); + case D3D_FEATURE_LEVEL_10_1: + return gl::Version(3, 0); + 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 gl::Version(2, 0); - // 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; + default: + UNREACHABLE(); + return gl::Version(0, 0); + } +} + +unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + 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 1; + default: + UNREACHABLE(); + return 0; + } +} - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; +bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel) +{ + // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders. + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return true; + default: + return false; + } +} - default: UNREACHABLE(); return 0; +unsigned int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + // D3D10+ only allows 1 sample mask. + 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 1u; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0u; + default: + UNREACHABLE(); + return 0u; } } 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) + for (GLenum internalFormat : allFormats) { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps); - textureCapsMap->insert(*internalFormat, textureCaps); + gl::TextureCaps textureCaps = GenerateTextureFormatCaps( + GetMaximumClientVersion(featureLevel), internalFormat, device, renderer11DeviceCaps); + textureCapsMap->insert(internalFormat, textureCaps); - maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); - - if (gl::GetInternalFormatInfo(*internalFormat).compressed) + if (gl::GetSizedInternalFormatInfo(internalFormat).compressed) { - caps->compressedTextureFormats.push_back(*internalFormat); + caps->compressedTextureFormats.push_back(internalFormat); } } @@ -1226,6 +1346,14 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons caps->maxVertexTextureImageUnits = static_cast<GLuint>(GetMaximumVertexTextureUnits(featureLevel)); + // Vertex Attribute Bindings are emulated on D3D11. + caps->maxVertexAttribBindings = caps->maxVertexAttributes; + // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11. + caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max(); + // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all + // platforms. + caps->maxVertexAttribStride = 2048; + // Fragment shader limits caps->maxFragmentUniformComponents = static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)) * 4; @@ -1239,10 +1367,28 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); + // Compute shader limits + caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel); + caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel); + caps->maxComputeWorkGroupInvocations = + static_cast<GLuint>(GetMaxComputeWorkGroupInvocations(featureLevel)); + caps->maxComputeUniformComponents = + static_cast<GLuint>(GetMaximumComputeUniformVectors(featureLevel)) * 4; + caps->maxComputeUniformBlocks = + static_cast<GLuint>(GetMaximumComputeUniformBlocks(featureLevel)); + caps->maxComputeTextureImageUnits = + static_cast<GLuint>(GetMaximumComputeTextureUnits(featureLevel)); + caps->maxImageUnits = static_cast<GLuint>(GetMaximumImageUnits(featureLevel)); + caps->maxComputeImageUniforms = + static_cast<GLuint>(GetMaximumComputeImageUniforms(featureLevel)); + // Aggregate shader limits caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1. + caps->maxUniformLocations = 1024; + // 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 @@ -1254,6 +1400,9 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons static_cast<GLint64>(caps->maxVertexUniformComponents); caps->maxCombinedFragmentUniformComponents = (static_cast<GLint64>(caps->maxFragmentUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) + static_cast<GLint64>(caps->maxFragmentUniformComponents); + caps->maxCombinedComputeUniformComponents = + static_cast<GLuint>(caps->maxComputeUniformBlocks * (caps->maxUniformBlockSize / 4) + + caps->maxComputeUniformComponents); caps->maxVaryingComponents = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4; caps->maxVaryingVectors = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)); @@ -1267,8 +1416,21 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons caps->maxTransformFeedbackSeparateComponents = static_cast<GLuint>(GetMaximumStreamOutputSeparateComponents(featureLevel)); - // Multisample limits - caps->maxSamples = maxSamples; + // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values + // are determined according to available sample counts for each individual format. + caps->maxSamples = std::numeric_limits<GLint>::max(); + caps->maxColorTextureSamples = std::numeric_limits<GLint>::max(); + caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max(); + caps->maxIntegerSamples = std::numeric_limits<GLint>::max(); + + // Sample mask words limits + caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel); + + // Framebuffer limits + caps->maxFramebufferSamples = std::numeric_limits<GLint>::max(); + caps->maxFramebufferWidth = + static_cast<GLuint>(GetMaximumRenderToBufferWindowSize(featureLevel)); + caps->maxFramebufferHeight = caps->maxFramebufferWidth; // GL extension support extensions->setTextureExtensionSupport(*textureCapsMap); @@ -1286,12 +1448,15 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons 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; + // Direct3D guarantees to return zero for any resource that is accessed out of bounds. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx + // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx + extensions->robustBufferAccessBehavior = true; extensions->blendMinMax = true; extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); @@ -1300,17 +1465,29 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); extensions->fragDepth = true; + extensions->multiview = IsMultiviewSupported(featureLevel); + if (extensions->multiview) + { + extensions->maxViews = + std::min(static_cast<GLuint>(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS), + std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)), + GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel))); + } 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->vertexArrayObject = true; - extensions->noError = 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. @@ -1340,8 +1517,355 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons #endif } +void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) +{ + size_t indexKey = static_cast<size_t>(ceil(log(sampleCount))); + ASSERT(indexKey < kSamplePositions.size() && + (2 * index + 1) < kSamplePositions[indexKey].size()); + + xy[0] = kSamplePositions[indexKey][2 * index]; + xy[1] = kSamplePositions[indexKey][2 * index + 1]; +} + } // 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, gl::CullFaceMode cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case gl::CullFaceMode::Front: + cull = D3D11_CULL_FRONT; + break; + case gl::CullFaceMode::Back: + cull = D3D11_CULL_BACK; + break; + case gl::CullFaceMode::FrontAndBack: + 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; + } +} + +// Get the D3D11 write mask covering all color channels of a given format +UINT8 GetColorMask(const gl::InternalFormat &format) +{ + return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0, + format.alphaBits > 0); +} + +} // namespace gl_d3d11 + namespace d3d11 { @@ -1352,9 +1876,7 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) IDXGIDevice *dxgiDevice = nullptr; IDXGIAdapter *dxgiAdapter = nullptr; -#if defined(ANGLE_ENABLE_D3D11_1) IDXGIAdapter2 *dxgiAdapter2 = nullptr; -#endif ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN; @@ -1365,7 +1887,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) if (SUCCEEDED(hr)) { std::wstring adapterString; -#if defined(ANGLE_ENABLE_D3D11_1) HRESULT adapter2hr = dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2); if (SUCCEEDED(adapter2hr)) @@ -1378,7 +1899,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) adapterString = std::wstring(adapterDesc2.Description); } else -#endif { DXGI_ADAPTER_DESC adapterDesc; dxgiAdapter->GetDesc(&adapterDesc); @@ -1410,16 +1930,14 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) SafeRelease(dxgiDevice); SafeRelease(dxgiAdapter); -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(dxgiAdapter2); -#endif return retDeviceType; } void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) { - const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + 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. @@ -1433,7 +1951,10 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi upsampleCount++; } } - *levelOffset = upsampleCount; + if (levelOffset) + { + *levelOffset = upsampleCount; + } } void GenerateInitialTextureData(GLint internalFormat, @@ -1445,10 +1966,11 @@ void GenerateInitialTextureData(GLint internalFormat, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, std::vector<std::vector<BYTE>> *outData) { - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); - ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); + const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat); outSubresourceData->resize(mipLevels); outData->resize(mipLevels); @@ -1495,6 +2017,36 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo vertex->s = s; } +BlendStateKey::BlendStateKey() +{ + memset(this, 0, sizeof(BlendStateKey)); +} + +bool operator==(const BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; +} + +bool operator!=(const BlendStateKey &a, const BlendStateKey &b) +{ + return !(a == b); +} + +RasterizerStateKey::RasterizerStateKey() +{ + memset(this, 0, sizeof(RasterizerStateKey)); +} + +bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return !(a == b); +} + HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { #if defined(_DEBUG) @@ -1533,34 +2085,66 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) #endif } +// Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling +// allocateResource is only compatible with Clang and MSVS, which support calling a +// method on a forward declared class in a template. +template <ResourceType ResourceT> +gl::Error LazyResource<ResourceT>::resolveImpl(Renderer11 *renderer, + const GetDescType<ResourceT> &desc, + GetInitDataType<ResourceT> *initData, + const char *name) +{ + if (!mResource.valid()) + { + ANGLE_TRY(renderer->allocateResource(desc, initData, &mResource)); + mResource.setDebugName(name); + } + return gl::NoError(); +} + +template gl::Error LazyResource<ResourceType::BlendState>::resolveImpl(Renderer11 *renderer, + const D3D11_BLEND_DESC &desc, + void *initData, + const char *name); +template gl::Error LazyResource<ResourceType::ComputeShader>::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); +template gl::Error LazyResource<ResourceType::GeometryShader>::resolveImpl( + Renderer11 *renderer, + const ShaderData &desc, + const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData, + const char *name); +template gl::Error LazyResource<ResourceType::InputLayout>::resolveImpl( + Renderer11 *renderer, + const InputElementArray &desc, + const ShaderData *initData, + const char *name); +template gl::Error LazyResource<ResourceType::PixelShader>::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); +template gl::Error LazyResource<ResourceType::VertexShader>::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); + 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) + : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName) { - memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); } -ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +LazyInputLayout::~LazyInputLayout() { - checkAssociatedDevice(device); - - if (mResource == nullptr) - { - HRESULT result = - device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()), - mByteCode, mByteCodeLen, &mResource); - ASSERT(SUCCEEDED(result)); - UNUSED_ASSERTION_VARIABLE(result); - d3d11::SetDebugName(mResource, mDebugName); - } +} - return mResource; +gl::Error LazyInputLayout::resolve(Renderer11 *renderer) +{ + return resolveImpl(renderer, mInputDesc, &mByteCode, mDebugName); } LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName) @@ -1568,213 +2152,270 @@ LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugNa { } -ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) +gl::Error LazyBlendState::resolve(Renderer11 *renderer) +{ + return resolveImpl(renderer, mDesc, nullptr, mDebugName); +} + +angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, + const DXGI_ADAPTER_DESC &adapterDesc) { - checkAssociatedDevice(device); + bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); - if (mResource == nullptr) + angle::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)) { - HRESULT result = device->CreateBlendState(&mDesc, &mResource); - ASSERT(SUCCEEDED(result)); - UNUSED_ASSERTION_VARIABLE(result); - d3d11::SetDebugName(mResource, mDebugName); + 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; + } } - return mResource; + // TODO(jmadill): Disable workaround when we have a fixed compiler DLL. + workarounds.expandIntegerPowExpressions = true; + + workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId); + workarounds.getDimensionsIgnoresBaseLevel = IsNvidia(adapterDesc.VendorId); + + if (IsIntel(adapterDesc.VendorId)) + { + IntelDriverVersion capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion); + + workarounds.preAddTexelFetchOffsets = true; + workarounds.useSystemMemoryForConstantBuffers = true; + workarounds.disableB5G6R5Support = capsVersion < IntelDriverVersion(4539); + workarounds.addDummyTextureNoRenderTarget = capsVersion < IntelDriverVersion(4815); + if (IsSkylake(adapterDesc.DeviceId)) + { + workarounds.callClearTwice = capsVersion < IntelDriverVersion(4771); + workarounds.emulateIsnanFloat = capsVersion < IntelDriverVersion(4542); + } + else if (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId)) + { + workarounds.rewriteUnaryMinusOperator = capsVersion < IntelDriverVersion(4624); + } + } + + // 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; + } + + // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to + // select the viewport / RT array index in the geometry shader. + workarounds.selectViewInGeometryShader = + (deviceCaps.supportsVpRtIndexWriteFromVertexShader == false); + + // Call platform hooks for testing overrides. + auto *platform = ANGLEPlatformCurrent(); + platform->overrideWorkaroundsD3D(platform, &workarounds); + + return workarounds; } -WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) +void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth) { - WorkaroundsD3D workarounds; - workarounds.mrtPerfWorkaround = true; - workarounds.setDataFasterThanImageUpload = true; - workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); - workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3); - return workarounds; + 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), - mSampleCount(0), - mTexture2D(nullptr), - mTexture3D(nullptr) +// TextureHelper11 implementation. +TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) { } -TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) - : mTextureType(toCopy.mTextureType), - mExtents(toCopy.mExtents), - mFormat(toCopy.mFormat), - mSampleCount(toCopy.mSampleCount), - mTexture2D(toCopy.mTexture2D), - mTexture3D(toCopy.mTexture3D) +TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11() { - toCopy.reset(); + *this = std::move(toCopy); } -// static -TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource) +TextureHelper11::TextureHelper11(const TextureHelper11 &other) + : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount) { - TextureHelper11 newHelper; - 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; + mData = other.mData; } -// static -TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn) +TextureHelper11::~TextureHelper11() { - TextureHelper11 newHelper; - newHelper.mTexture2D = texToOwn; - newHelper.mTextureType = GL_TEXTURE_2D; - newHelper.initDesc(); - return newHelper; } -// static -TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn) +void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const { - TextureHelper11 newHelper; - newHelper.mTexture3D = texToOwn; - newHelper.mTextureType = GL_TEXTURE_3D; - newHelper.initDesc(); - return newHelper; + static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc); } -void TextureHelper11::initDesc() +void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const { - if (mTextureType == GL_TEXTURE_2D) - { - ASSERT(!mTexture3D); - D3D11_TEXTURE2D_DESC desc2D; - mTexture2D->GetDesc(&desc2D); + static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc); +} - 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); +void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D) +{ + mData->resourceType = ResourceType::Texture2D; + mExtents.width = static_cast<int>(desc2D.Width); + mExtents.height = static_cast<int>(desc2D.Height); + mExtents.depth = 1; + mSampleCount = desc2D.SampleDesc.Count; +} - 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; - } +void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D) +{ + mData->resourceType = ResourceType::Texture3D; + mExtents.width = static_cast<int>(desc3D.Width); + mExtents.height = static_cast<int>(desc3D.Height); + mExtents.depth = static_cast<int>(desc3D.Depth); + mSampleCount = 1; } -TextureHelper11::~TextureHelper11() +TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other) { - SafeRelease(mTexture2D); - SafeRelease(mTexture3D); + std::swap(mData, other.mData); + std::swap(mExtents, other.mExtents); + std::swap(mFormatSet, other.mFormatSet); + std::swap(mSampleCount, other.mSampleCount); + return *this; } -ID3D11Resource *TextureHelper11::getResource() const +TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other) { - return mTexture2D ? static_cast<ID3D11Resource *>(mTexture2D) - : static_cast<ID3D11Resource *>(mTexture3D); + mData = other.mData; + mExtents = other.mExtents; + mFormatSet = other.mFormatSet; + mSampleCount = other.mSampleCount; + return *this; } -TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture) +bool TextureHelper11::operator==(const TextureHelper11 &other) const { - SafeRelease(mTexture2D); - SafeRelease(mTexture3D); + return mData->object == other.mData->object; +} - mTextureType = texture.mTextureType; - mExtents = texture.mExtents; - mFormat = texture.mFormat; - mSampleCount = texture.mSampleCount; - mTexture2D = texture.mTexture2D; - mTexture3D = texture.mTexture3D; - texture.reset(); - return *this; +bool TextureHelper11::operator!=(const TextureHelper11 &other) const +{ + return mData->object != other.mData->object; } -void TextureHelper11::reset() +bool UsePresentPathFast(const Renderer11 *renderer, + const gl::FramebufferAttachment *framebufferAttachment) +{ + if (framebufferAttachment == nullptr) + { + return false; + } + + return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && + renderer->presentPathFastEnabled()); +} + +bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type) { - mTextureType = GL_NONE; - mExtents = gl::Extents(); - mFormat = DXGI_FORMAT_UNKNOWN; - mSampleCount = 0; - mTexture2D = nullptr; - mTexture3D = nullptr; + // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT + // indices, since we restrict it via MAX_ELEMENT_INDEX. + return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT); } -gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType, - DXGI_FORMAT dxgiFormat, - const gl::Extents &size, - ID3D11Device *device) +bool IsStreamingIndexData(const gl::Context *context, GLenum srcType) { - if (textureType == GL_TEXTURE_2D) + const auto &glState = context->getGLState(); + gl::Buffer *glBuffer = glState.getVertexArray()->getElementArrayBuffer().get(); + + // Case 1: the indices are passed by pointer, which forces the streaming of index data + if (glBuffer == nullptr) { - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = size.width; - stagingDesc.Height = size.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = dxgiFormat; - 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; + return true; + } - 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); - } + bool primitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType); + + BufferD3D *buffer = GetImplAs<BufferD3D>(glBuffer); + const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) + ? GL_UNSIGNED_INT + : GL_UNSIGNED_SHORT; - return TextureHelper11::MakeAndPossess2D(stagingTex); + // Case 2a: the buffer can be used directly + if (buffer->supportsDirectBinding() && dstType == srcType) + { + return false; } - 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 = dxgiFormat; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; + // Case 2b: use a static translated copy or fall back to streaming + StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer(); + if (staticBuffer == nullptr) + { + return true; + } - ID3D11Texture3D *stagingTex = nullptr; - HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex); - if (FAILED(result)) + if ((staticBuffer->getBufferSize() == 0) || (staticBuffer->getIndexType() != dstType)) { - return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", - result); + return true; } - return TextureHelper11::MakeAndPossess3D(stagingTex); + return false; } -bool UsePresentPathFast(const Renderer11 *renderer, - const gl::FramebufferAttachment *framebufferAttachment) +IndexStorageType ClassifyIndexStorage(const gl::State &glState, + const gl::Buffer *elementArrayBuffer, + GLenum elementType, + GLenum destElementType, + unsigned int offset, + bool *needsTranslation) { - if (framebufferAttachment == nullptr) + // No buffer bound means we are streaming from a client pointer. + if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset)) { - return false; + *needsTranslation = true; + return IndexStorageType::Dynamic; } - return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && - renderer->presentPathFastEnabled()); + // The buffer can be used directly if the storage supports it and no translation needed. + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer); + if (bufferD3D->supportsDirectBinding() && destElementType == elementType) + { + *needsTranslation = false; + return IndexStorageType::Direct; + } + + // Use a static copy when available. + StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer(); + if (staticBuffer != nullptr) + { + // Need to re-translate the static data if has never been used, or changed type. + *needsTranslation = + (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != destElementType); + return IndexStorageType::Static; + } + + // Static buffer not available, fall back to streaming. + *needsTranslation = true; + return IndexStorageType::Dynamic; } } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h index 4925a2d227..3af51bb0f6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -11,12 +11,16 @@ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #include <array> +#include <functional> #include <vector> -#include "libANGLE/angletypes.h" +#include "common/Color.h" + #include "libANGLE/Caps.h" #include "libANGLE/Error.h" #include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" namespace gl { @@ -27,10 +31,10 @@ namespace rx { class Renderer11; class RenderTarget11; -struct WorkaroundsD3D; struct Renderer11DeviceCaps; -using RenderTargetArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>; +using RenderTargetArray = std::array<RenderTarget11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>; +using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>; namespace gl_d3d11 { @@ -39,7 +43,7 @@ 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_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode); D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); @@ -48,9 +52,12 @@ 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); +UINT8 GetColorMask(const gl::InternalFormat &formatInfo); + } // namespace gl_d3d11 namespace d3d11_gl @@ -60,10 +67,12 @@ unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel); unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel); -GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); +gl::Version 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); +void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy); + } // namespace d3d11_gl namespace d3d11 @@ -108,32 +117,45 @@ struct PositionLayerTexCoord3DVertex void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, unsigned int layer, float u, float v, float s); -template <typename T> -struct PositionDepthColorVertex +struct PositionVertex { - float x, y, z; - T r, g, b, a; + float x, y, z, w; }; -template <typename T> -void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, float y, float z, - const gl::Color<T> &color) +struct BlendStateKey final { - 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; -} + // This will zero-initialize the struct, including padding. + BlendStateKey(); + + gl::BlendState blendState; + + // An int so struct size rounds nicely. + uint32_t rtvMax; + + uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; +}; + +bool operator==(const BlendStateKey &a, const BlendStateKey &b); +bool operator!=(const BlendStateKey &a, const BlendStateKey &b); + +struct RasterizerStateKey final +{ + // This will zero-initialize the struct, including padding. + RasterizerStateKey(); + + gl::RasterizerState rasterizerState; -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + // Use a 32-bit int to round the struct nicely. + uint32_t scissorEnabled; +}; + +bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b); +bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b); template <typename outType> outType* DynamicCastComObject(IUnknown* object) { - outType *outObject = NULL; + outType *outObject = nullptr; HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject)); if (SUCCEEDED(result)) { @@ -142,7 +164,7 @@ outType* DynamicCastComObject(IUnknown* object) else { SafeRelease(outObject); - return NULL; + return nullptr; } } @@ -161,143 +183,63 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -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) +template <ResourceType ResourceT> +class LazyResource : angle::NonCopyable { - return CompileGS(device, byteCode, N, name); -} + public: + constexpr LazyResource() : mResource() {} + virtual ~LazyResource() {} -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)) + virtual gl::Error resolve(Renderer11 *renderer) = 0; + void reset() { mResource.reset(); } + GetD3D11Type<ResourceT> *get() const { - SetDebugName(ps, name); - return ps; + ASSERT(mResource.valid()); + return mResource.get(); } - 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); } + const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; } protected: - void checkAssociatedDevice(ID3D11Device *device); + LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {} - ResourceType *mResource; - ID3D11Device *mAssociatedDevice; -}; + // Specialized in the cpp file to avoid MSVS/Clang specific code. + gl::Error resolveImpl(Renderer11 *renderer, + const GetDescType<ResourceT> &desc, + GetInitDataType<ResourceT> *initData, + const char *name); -template <typename ResourceType> -void LazyResource<ResourceType>::checkAssociatedDevice(ID3D11Device *device) -{ - ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice); - mAssociatedDevice = device; -} + Resource11<GetD3D11Type<ResourceT>> mResource; +}; template <typename D3D11ShaderType> -class LazyShader final : public LazyResource<D3D11ShaderType> +class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<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) + constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name) + : mByteCode(byteCode, 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) + constexpr LazyShader(LazyShader &&shader) + : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)), + mByteCode(std::move(shader.mByteCode)), + mName(shader.mName) { - mResource = CompileVS(device, mByteCode, mByteCodeSize, mName); } - return mResource; -} -template <> -inline ID3D11GeometryShader *LazyShader<ID3D11GeometryShader>::resolve(ID3D11Device *device) -{ - checkAssociatedDevice(device); - if (mResource == nullptr) + gl::Error resolve(Renderer11 *renderer) override { - mResource = CompileGS(device, mByteCode, mByteCodeSize, mName); + return this->resolveImpl(renderer, mByteCode, nullptr, mName); } - return mResource; -} -template <> -inline ID3D11PixelShader *LazyShader<ID3D11PixelShader>::resolve(ID3D11Device *device) -{ - checkAssociatedDevice(device); - if (mResource == nullptr) - { - mResource = CompilePS(device, mByteCode, mByteCodeSize, mName); - } - return mResource; -} + private: + ShaderData mByteCode; + const char *mName; +}; -class LazyInputLayout final : public LazyResource<ID3D11InputLayout> +class LazyInputLayout final : public LazyResource<ResourceType::InputLayout> { public: LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, @@ -305,22 +247,22 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout> const BYTE *byteCode, size_t byteCodeLen, const char *debugName); + ~LazyInputLayout() override; - ID3D11InputLayout *resolve(ID3D11Device *device) override; + gl::Error resolve(Renderer11 *renderer) override; private: - std::vector<D3D11_INPUT_ELEMENT_DESC> mInputDesc; - size_t mByteCodeLen; - const BYTE *mByteCode; + InputElementArray mInputDesc; + ShaderData mByteCode; const char *mDebugName; }; -class LazyBlendState final : public LazyResource<ID3D11BlendState> +class LazyBlendState final : public LazyResource<ResourceType::BlendState> { public: LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName); - ID3D11BlendState *resolve(ID3D11Device *device) override; + gl::Error resolve(Renderer11 *renderer) override; private: D3D11_BLEND_DESC mDesc; @@ -342,48 +284,147 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c } } -WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); +angle::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 +struct GenericData +{ + GenericData() {} + ~GenericData() + { + if (object) + { + // We can have a nullptr factory when holding passed-in resources. + if (manager) + { + manager->onReleaseGeneric(resourceType, object); + manager = nullptr; + } + object->Release(); + object = nullptr; + } + } + + ResourceType resourceType = ResourceType::Last; + ID3D11Resource *object = nullptr; + ResourceManager11 *manager = nullptr; +}; + // A helper class which wraps a 2D or 3D texture. -class TextureHelper11 : angle::NonCopyable +class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData> { public: TextureHelper11(); - TextureHelper11(TextureHelper11 &&toCopy); - ~TextureHelper11(); - TextureHelper11 &operator=(TextureHelper11 &&texture); - - static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource); - static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn); - static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn); - - GLenum getTextureType() const { return mTextureType; } + TextureHelper11(TextureHelper11 &&other); + TextureHelper11(const TextureHelper11 &other); + ~TextureHelper11() override; + TextureHelper11 &operator=(TextureHelper11 &&other); + TextureHelper11 &operator=(const TextureHelper11 &other); + + bool is2D() const { return mData->resourceType == ResourceType::Texture2D; } + bool is3D() const { return mData->resourceType == ResourceType::Texture3D; } + ResourceType getTextureType() const { return mData->resourceType; } gl::Extents getExtents() const { return mExtents; } - DXGI_FORMAT getFormat() const { return mFormat; } + DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; } + 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; + + template <typename DescT, typename ResourceT> + void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format) + { + std::swap(mData->manager, texture.mData->manager); + + // Can't use std::swap because texture is typed, and here we use ID3D11Resource. + ID3D11Resource *temp = mData->object; + mData->object = texture.mData->object; + texture.mData->object = static_cast<ResourceT *>(temp); + + mFormatSet = &format; + initDesc(desc); + } + + template <typename ResourceT> + void set(ResourceT *object, const d3d11::Format &format) + { + ASSERT(!valid()); + mFormatSet = &format; + mData->object = object; + mData->manager = nullptr; + + GetDescFromD3D11<ResourceT> desc; + getDesc(&desc); + initDesc(desc); + } + + bool operator==(const TextureHelper11 &other) const; + bool operator!=(const TextureHelper11 &other) const; + + void getDesc(D3D11_TEXTURE2D_DESC *desc) const; + void getDesc(D3D11_TEXTURE3D_DESC *desc) const; private: - void reset(); - void initDesc(); + void initDesc(const D3D11_TEXTURE2D_DESC &desc2D); + void initDesc(const D3D11_TEXTURE3D_DESC &desc3D); - GLenum mTextureType; + const d3d11::Format *mFormatSet; gl::Extents mExtents; - DXGI_FORMAT mFormat; int mSampleCount; - ID3D11Texture2D *mTexture2D; - ID3D11Texture3D *mTexture3D; }; -gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType, - DXGI_FORMAT dxgiFormat, - const gl::Extents &size, - ID3D11Device *device); +enum class StagingAccess +{ + READ, + READ_WRITE, +}; bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); +bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type); +bool IsStreamingIndexData(const gl::Context *context, GLenum srcType); + +enum class IndexStorageType +{ + // Dynamic indexes are re-streamed every frame. They come from a client data pointer or + // from buffers that are updated frequently. + Dynamic, + + // Static indexes are translated from the original storage once, and re-used multiple times. + Static, + + // Direct indexes are never transated and are used directly from the source buffer. They are + // the fastest available path. + Direct, + + // Not a real storage type. + Invalid, +}; + +IndexStorageType ClassifyIndexStorage(const gl::State &glState, + const gl::Buffer *elementArrayBuffer, + GLenum elementType, + GLenum destElementType, + unsigned int offset, + bool *needsTranslation); + +// Used for state change notifications between buffers and vertex arrays. +using OnBufferDataDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>; +using OnBufferDataDirtyChannel = angle::BroadcastChannel<size_t, const gl::Context *>; +using OnBufferDataDirtyReceiver = angle::SignalReceiver<size_t, const gl::Context *>; + +// Used for state change notifications between RenderTarget11 and Framebuffer11. +using OnRenderTargetDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>; +using OnRenderTargetDirtyChannel = angle::BroadcastChannel<size_t, const gl::Context *>; +using OnRenderTargetDirtyReceiver = angle::SignalReceiver<size_t, const gl::Context *>; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl index 2b3e1ebe4c..48f5b427ec 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -1,13 +1,152 @@ -// Assume we are in SM4+, which has 8 color outputs +// +// Copyright (c) 2017 The ANGLE Project. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// -void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +// Clear11.hlsl: Shaders for clearing RTVs and DSVs using draw calls and +// specifying float depth values and either float, uint or sint clear colors. +// Notes: +// - UINT & SINT clears can only be compiled with FL10+ +// - VS_Clear_FL9 requires a VB to be bound with vertices to create +// a primitive covering the entire surface (in clip co-ordinates) + +// Constants +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), +}; + +// Vertex Shaders +void VS_Clear(in uint id : SV_VertexID, + out float4 outPosition : SV_POSITION) +{ + float2 corner = g_Corners[id]; + outPosition = float4(corner.x, corner.y, 0.0f, 1.0f); +} + +void VS_Multiview_Clear(in uint id : SV_VertexID, + in uint instanceID : SV_InstanceID, + out float4 outPosition : SV_POSITION, + out uint outLayerID : TEXCOORD0) +{ + float2 corner = g_Corners[id]; + outPosition = float4(corner.x, corner.y, 0.0f, 1.0f); + outLayerID = instanceID; +} + +void VS_Clear_FL9( in float4 inPosition : POSITION, + out float4 outPosition : SV_POSITION) +{ + outPosition = inPosition; +} + +// Geometry shader for clearing multiview layered textures +struct GS_INPUT +{ + float4 inPosition : SV_Position; + uint inLayerID : TEXCOORD0; +}; + +struct GS_OUTPUT { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; + float4 outPosition : SV_Position; + uint outLayerID : SV_RenderTargetArrayIndex; +}; + +[maxvertexcount(3)] +void GS_Multiview_Clear(triangle GS_INPUT input[3], inout TriangleStream<GS_OUTPUT> outStream) +{ + GS_OUTPUT output = (GS_OUTPUT)0; + for (int i = 0; i < 3; i++) + { + output.outPosition = input[i].inPosition; + output.outLayerID = input[i].inLayerID; + outStream.Append(output); + } + outStream.RestartStrip(); +} + +// Pixel Shader Constant Buffers +cbuffer ColorAndDepthDataFloat : register(b0) +{ + float4 color_Float : packoffset(c0); + float zValueF_Float : packoffset(c1); +} + +cbuffer ColorAndDepthDataSint : register(b0) +{ + int4 color_Sint : packoffset(c0); + float zValueF_Sint : packoffset(c1); +} + +cbuffer ColorAndDepthDataUint : register(b0) +{ + uint4 color_Uint : packoffset(c0); + float zValueF_Uint : packoffset(c1); } -struct PS_OutputFloat +cbuffer DepthOnlyData : register(b0) +{ + float zValue_Depth : packoffset(c1); +} + +// Pixel Shader Output Structs +struct PS_OutputFloat_FL9 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat1 +{ + float4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat2 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat3 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat4 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat5 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat6 { float4 color0 : SV_TARGET0; float4 color1 : SV_TARGET1; @@ -15,50 +154,98 @@ struct PS_OutputFloat float4 color3 : SV_TARGET3; float4 color4 : SV_TARGET4; float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; + float depth : SV_DEPTH; }; -PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +struct PS_OutputFloat7 { - 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; -} + 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; + float depth : SV_DEPTH; +}; -struct PS_OutputFloat_FL9 +struct PS_OutputFloat8 { 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; + float depth : SV_DEPTH; }; -PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +struct PS_OutputUint1 { - PS_OutputFloat_FL9 outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; - return outColor; -} + uint4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; -void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +struct PS_OutputUint2 { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint3 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint4 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint5 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint6 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint7 +{ + 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; + float depth : SV_DEPTH; +}; -struct PS_OutputUint +struct PS_OutputUint8 { uint4 color0 : SV_TARGET0; uint4 color1 : SV_TARGET1; @@ -68,31 +255,73 @@ struct PS_OutputUint uint4 color5 : SV_TARGET5; uint4 color6 : SV_TARGET6; uint4 color7 : SV_TARGET7; + float depth : SV_DEPTH; }; -PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +struct PS_OutputSint1 { - 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; -} + int4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; +struct PS_OutputSint2 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; -void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +struct PS_OutputSint3 { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint4 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint5 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint6 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint7 +{ + 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; + float depth : SV_DEPTH; +}; -struct PS_OutputSint +struct PS_OutputSint8 { int4 color0 : SV_TARGET0; int4 color1 : SV_TARGET1; @@ -102,18 +331,305 @@ struct PS_OutputSint int4 color5 : SV_TARGET5; int4 color6 : SV_TARGET6; int4 color7 : SV_TARGET7; + float depth : SV_DEPTH; +}; + +struct PS_OutputDepth +{ + float depth : SV_DEPTH; }; -PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +// Pixel Shaders +PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat_FL9 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat1 PS_ClearFloat1(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat1 outData; + outData.color0 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat2 PS_ClearFloat2(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat2 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat3 PS_ClearFloat3(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat3 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat4 PS_ClearFloat4(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat4 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat5 PS_ClearFloat5(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat5 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat6 PS_ClearFloat6(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat6 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat7 PS_ClearFloat7(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat7 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.color6 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat8 PS_ClearFloat8(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat8 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.color6 = color_Float; + outData.color7 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputUint1 PS_ClearUint1(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint1 outData; + outData.color0 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint2 PS_ClearUint2(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint2 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint3 PS_ClearUint3(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint3 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint4 PS_ClearUint4(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint4 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint5 PS_ClearUint5(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint5 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint6 PS_ClearUint6(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint6 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint7 PS_ClearUint7(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint7 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.color6 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint8 PS_ClearUint8(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint8 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.color6 = color_Uint; + outData.color7 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputSint1 PS_ClearSint1(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint1 outData; + outData.color0 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint2 PS_ClearSint2(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint2 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint3 PS_ClearSint3(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint3 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint4 PS_ClearSint4(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint4 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint5 PS_ClearSint5(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint5 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint6 PS_ClearSint6(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint6 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint7 PS_ClearSint7(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint7 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.color6 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint8 PS_ClearSint8(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint8 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.color6 = color_Sint; + outData.color7 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputDepth PS_ClearDepth(in float4 inPosition : SV_POSITION) { - 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; + PS_OutputDepth outData; + outData.depth = zValue_Depth; + return outData; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl new file mode 100644 index 0000000000..0d10b8eafa --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl @@ -0,0 +1,131 @@ +Texture2D<float4> TextureF : register(t0); +Texture2D<uint4> TextureUI : register(t0); + +SamplerState Sampler : register(s0); + +// Notation: +// PM: premultiply, UM: unmulitply, PT: passthrough +// F: float, U: uint + +// Float to float LUMA +float4 PS_FtoF_PM_LUMA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb = color.r * color.a; + color.a = 1.0f; + return color; +} +float4 PS_FtoF_UM_LUMA(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.r / color.a; + } + color.a = 1.0f; + return color; +} + +// Float to float LUMAALPHA +float4 PS_FtoF_PM_LUMAALPHA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb = color.r * color.a; + return color; +} + +float4 PS_FtoF_UM_LUMAALPHA(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.r / color.a; + } + return color; +} + +// Float to float RGBA +float4 PS_FtoF_PM_RGBA(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_FtoF_UM_RGBA(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; +} + +// Float to float RGB +float4 PS_FtoF_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + color.a = 1.0f; + return color; +} + +float4 PS_FtoF_UM_RGB(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; + } + color.a = 1.0f; + return color; +} + +// Float to uint RGBA +uint4 PS_FtoU_PT_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + return uint4(color * 255); +} + +uint4 PS_FtoU_PM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return uint4(color * 255); +} + +uint4 PS_FtoU_UM_RGBA(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 uint4(color * 255); +} + +// Float to uint RGB +uint4 PS_FtoU_PT_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + return uint4(color.rgb * 255, 1); +} + +uint4 PS_FtoU_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return uint4(color.rgb * 255, 1); +} + +uint4 PS_FtoU_UM_RGB(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 uint4(color.rgb * 255, 1); +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl index 8671c39fb7..0b1a5ad169 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -1,4 +1,5 @@ Texture2D<float4> TextureF : register(t0); +Texture2DMS<float4> TextureF_MS: register(t0); Texture2D<uint4> TextureUI : register(t0); Texture2D<int4> TextureI : register(t0); @@ -21,6 +22,16 @@ float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexC return TextureF.Sample(Sampler, inTexCoord).rgba; } +float4 PS_PassthroughA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(0.0f, 0.0f, 0.0f, TextureF.Sample(Sampler, inTexCoord).a); +} + +float4 PS_PassthroughRGBA2DMS(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCORD0, in uint inSampleIndex : SV_SAMPLEINDEX) : SV_TARGET0 +{ + return TextureF_MS.sample[inSampleIndex][inTexCoord].rgba; +} + uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 { uint2 size; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl new file mode 100644 index 0000000000..7dc40d4b6a --- /dev/null +++ b/src/3rdparty/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_Depth) +{ + // 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h new file mode 100644 index 0000000000..a5cccdc98e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h @@ -0,0 +1,155 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// TextureF_MS texture float4 2dMS t0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCORD 0 xy 1 NONE float xy +// SV_SAMPLEINDEX 0 x 2 SAMPLE uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +// Pixel Shader runs at sample frequency +// +ps_4_1 +dcl_globalFlags refactoringAllowed +dcl_resource_texture2dms(0) (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_input_ps_sgv constant v2.x, sampleIndex +dcl_output o0.xyzw +dcl_temps 1 +ftou r0.xy, v1.xyxx +mov r0.zw, l(0,0,0,0) +ldms o0.xyzw, r0.xyzw, t0.xyzw, v2.x +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_PS_PassthroughRGBA2DMS[] = +{ + 68, 88, 66, 67, 206, 115, + 73, 27, 160, 237, 59, 223, + 179, 180, 28, 146, 74, 174, + 29, 197, 1, 0, 0, 0, + 136, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 172, 0, 0, 0, 40, 1, + 0, 0, 92, 1, 0, 0, + 12, 2, 0, 0, 82, 68, + 69, 70, 112, 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, + 72, 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, 13, 0, 0, 0, + 84, 101, 120, 116, 117, 114, + 101, 70, 95, 77, 83, 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, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 116, 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, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 100, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 1, 1, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 82, 68, 0, 83, 86, + 95, 83, 65, 77, 80, 76, + 69, 73, 78, 68, 69, 88, + 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, 168, 0, + 0, 0, 65, 0, 0, 0, + 42, 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, + 99, 8, 0, 4, 18, 16, + 16, 0, 2, 0, 0, 0, + 10, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 28, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 1, 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, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 2, 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, 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, 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, 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 +}; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json deleted file mode 100644 index 3e9e6877d9..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "GL_UNSIGNED_NORMALIZED": { - "8": { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - }, - "16": { - "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM" - }, - "24": { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - }, - "32": { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - }, - "GL_SIGNED_NORMALIZED": { - "8": { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" - } - }, - "GL_FLOAT": { - "16": { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - }, - "32": { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - }, - "GL_UNSIGNED_INT": { - "8": { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" - }, - "16": { - "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" - }, - "32": { - "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" - } - }, - "GL_INT": { - "8": { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" - }, - "16": { - "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" - }, - "32": { - "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" - } - } -}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h deleted file mode 100644 index df9a30ff50..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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. -// -// swizzle_format_info: -// Provides information for swizzle format and a map from type->formatinfo -// - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ - -#include <GLES2/gl2.h> -#include <map> - -#include "common/platform.h" - -namespace rx -{ - -namespace d3d11 -{ - -struct SwizzleSizeType -{ - size_t maxComponentSize; - GLenum componentType; - - SwizzleSizeType(); - SwizzleSizeType(size_t maxComponentSize, GLenum componentType); - - bool operator<(const SwizzleSizeType &other) const; -}; - -struct SwizzleFormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - - SwizzleFormatInfo(); - SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat); -}; - -const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType); - -} // namespace d3d11 - -} // namespace rx - -#endif // LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp deleted file mode 100644 index 84d6fada97..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// GENERATED FILE - DO NOT EDIT -// Generated by gen_swizzle_format_table.py using data from swizzle_format_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. -// -// swizzle_format_info: -// Provides information for swizzle format and a map from type->formatinfo -// - -#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h" - -#include <GLES3/gl3.h> - -namespace rx -{ - -namespace d3d11 -{ - -SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE) -{ -} - -SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType) - : maxComponentSize(maxComponentSize), componentType(componentType) -{ -} - -bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const -{ - return (maxComponentSize != other.maxComponentSize) - ? (maxComponentSize < other.maxComponentSize) - : (componentType < other.componentType); -} - -SwizzleFormatInfo::SwizzleFormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), - mSRVFormat(DXGI_FORMAT_UNKNOWN), - mRTVFormat(DXGI_FORMAT_UNKNOWN) -{ -} - -SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, - DXGI_FORMAT rtvFormat) - : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) -{ -} - -const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType) -{ - // clang-format off - switch (componentType) - { - case GL_FLOAT: - { - switch (maxBits) - { - case 16: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT); - return formatInfo; - } - case 32: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT); - return formatInfo; - } - default: - break; - } - } - case GL_INT: - { - switch (maxBits) - { - case 16: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT); - return formatInfo; - } - case 32: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT); - return formatInfo; - } - case 8: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT); - return formatInfo; - } - default: - break; - } - } - case GL_SIGNED_NORMALIZED: - { - switch (maxBits) - { - case 8: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM); - return formatInfo; - } - default: - break; - } - } - case GL_UNSIGNED_INT: - { - switch (maxBits) - { - case 16: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT); - return formatInfo; - } - case 32: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT); - return formatInfo; - } - case 8: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT); - return formatInfo; - } - default: - break; - } - } - case GL_UNSIGNED_NORMALIZED: - { - switch (maxBits) - { - case 16: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R16G16B16A16_UNORM); - return formatInfo; - } - case 24: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT); - return formatInfo; - } - case 32: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT); - return formatInfo; - } - case 8: - { - static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM); - return formatInfo; - } - default: - break; - } - } - - default: - { - static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return defaultInfo; - } - } - // clang-format on - -} // GetSwizzleFormatInfo - -} // namespace d3d11 - -} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json index 87d303437f..61cd44a62b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json @@ -1,692 +1,523 @@ { - "GL_ALPHA": [ - { - "texFormat": "DXGI_FORMAT_A8_UNORM", - "srvFormat": "DXGI_FORMAT_A8_UNORM", - "rtvFormat": "DXGI_FORMAT_A8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - }, - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_ALPHA16F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - } - ], - "GL_ALPHA32F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - ], - "GL_ALPHA8_EXT": [ - { - "texFormat": "DXGI_FORMAT_A8_UNORM", - "srvFormat": "DXGI_FORMAT_A8_UNORM", - "rtvFormat": "DXGI_FORMAT_A8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - }, - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_BGR5_A1_ANGLEX": [ - { - "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" - } - ], - "GL_BGRA4_ANGLEX": [ - { - "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" - } - ], - "GL_BGRA8_EXT": [ - { - "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" - } - ], - "GL_BGRA_EXT": [ - { - "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" - } - ], - "GL_COMPRESSED_R11_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8_UNORM", - "srvFormat": "DXGI_FORMAT_R8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_RG11_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8G8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_RGB8_ETC2": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_RGBA8_ETC2_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": [ - { - "texFormat": "DXGI_FORMAT_BC1_UNORM", - "srvFormat": "DXGI_FORMAT_BC1_UNORM" - } - ], - "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": [ - { - "texFormat": "DXGI_FORMAT_BC2_UNORM", - "srvFormat": "DXGI_FORMAT_BC2_UNORM" - } - ], - "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": [ - { - "texFormat": "DXGI_FORMAT_BC3_UNORM", - "srvFormat": "DXGI_FORMAT_BC3_UNORM" - } - ], - "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": [ - { - "texFormat": "DXGI_FORMAT_BC1_UNORM", - "srvFormat": "DXGI_FORMAT_BC1_UNORM" - } - ], - "GL_COMPRESSED_SIGNED_R11_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8_SNORM", - "srvFormat": "DXGI_FORMAT_R8_SNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_SIGNED_RG11_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8G8_SNORM", - "srvFormat": "DXGI_FORMAT_R8G8_SNORM", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_SRGB8_ETC2": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_DEPTH24_STENCIL8": [ - { + "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" + }, + "B8G8R8A8_UNORM_SRGB": { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "channels": "bgra", + "componentType": "unorm", + "bits": {"red": 8, "green": 8, "blue": 8,"alpha": 8}, + "siwzzleFormat": "GL_RGBA8" + }, + "BC1_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGB_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC2_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC2_UNORM", + "srvFormat": "DXGI_FORMAT_BC2_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC3_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC3_UNORM", + "srvFormat": "DXGI_FORMAT_BC3_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGB_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC2_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC2_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC2_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC3_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC3_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC3_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "D24_UNORM_S8_UINT": { + "FL10Plus": { "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL10Plus" + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS" }, - { - "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH32F_STENCIL8": [ - { - "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", - "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS", - "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT", - "requirementsFcn": "OnlyFL10Plus" + "FL9_3": { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT" }, - { - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH_COMPONENT16": [ - { + "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", - "dsvFormat": "DXGI_FORMAT_D16_UNORM", - "requirementsFcn": "OnlyFL10Plus" - }, - { - "texFormat": "DXGI_FORMAT_D16_UNORM", - "dsvFormat": "DXGI_FORMAT_D16_UNORM", - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH_COMPONENT24": [ - { - "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL10Plus" - }, - { - "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH_COMPONENT32F": [ - { - "texFormat": "DXGI_FORMAT_R32_TYPELESS", - "srvFormat": "DXGI_FORMAT_R32_FLOAT", - "dsvFormat": "DXGI_FORMAT_D32_FLOAT", - "requirementsFcn": "OnlyFL10Plus" + "srvFormat": "DXGI_FORMAT_R16_UNORM" }, - { - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH_COMPONENT32_OES": [ - { - "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL10Plus" - } - ], - "GL_ETC1_RGB8_OES": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": [ - { - "texFormat": "DXGI_FORMAT_BC1_UNORM", - "srvFormat": "DXGI_FORMAT_BC1_UNORM" - } - ], - "GL_LUMINANCE": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_LUMINANCE16F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - } - ], - "GL_LUMINANCE32F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - ], - "GL_LUMINANCE8_ALPHA8_EXT": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_LUMINANCE8_EXT": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_LUMINANCE_ALPHA": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_LUMINANCE_ALPHA16F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - } - ], - "GL_LUMINANCE_ALPHA32F_EXT": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - ], - "GL_NONE": [ - { - } - ], - "GL_R11F_G11F_B10F": [ - { - "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", - "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT" - } - ], - "GL_R16F": [ - { - "texFormat": "DXGI_FORMAT_R16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16_FLOAT" - } - ], - "GL_R16I": [ - { - "texFormat": "DXGI_FORMAT_R16_SINT", - "srvFormat": "DXGI_FORMAT_R16_SINT", - "rtvFormat": "DXGI_FORMAT_R16_SINT" - } - ], - "GL_R16UI": [ - { - "texFormat": "DXGI_FORMAT_R16_UINT", - "srvFormat": "DXGI_FORMAT_R16_UINT", - "rtvFormat": "DXGI_FORMAT_R16_UINT" - } - ], - "GL_R32F": [ - { - "texFormat": "DXGI_FORMAT_R32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32_FLOAT" - } - ], - "GL_R32I": [ - { - "texFormat": "DXGI_FORMAT_R32_SINT", - "srvFormat": "DXGI_FORMAT_R32_SINT", - "rtvFormat": "DXGI_FORMAT_R32_SINT" - } - ], - "GL_R32UI": [ - { - "texFormat": "DXGI_FORMAT_R32_UINT", - "srvFormat": "DXGI_FORMAT_R32_UINT", - "rtvFormat": "DXGI_FORMAT_R32_UINT" - } - ], - "GL_R8": [ - { - "texFormat": "DXGI_FORMAT_R8_UNORM", - "srvFormat": "DXGI_FORMAT_R8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8_UNORM" - } - ], - "GL_R8I": [ - { - "texFormat": "DXGI_FORMAT_R8_SINT", - "srvFormat": "DXGI_FORMAT_R8_SINT", - "rtvFormat": "DXGI_FORMAT_R8_SINT" - } - ], - "GL_R8UI": [ - { - "texFormat": "DXGI_FORMAT_R8_UINT", - "srvFormat": "DXGI_FORMAT_R8_UINT", - "rtvFormat": "DXGI_FORMAT_R8_UINT" - } - ], - "GL_R8_SNORM": [ - { - "texFormat": "DXGI_FORMAT_R8_SNORM", - "srvFormat": "DXGI_FORMAT_R8_SNORM" - } - ], - "GL_RG16F": [ - { - "texFormat": "DXGI_FORMAT_R16G16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT" - } - ], - "GL_RG16I": [ - { - "texFormat": "DXGI_FORMAT_R16G16_SINT", - "srvFormat": "DXGI_FORMAT_R16G16_SINT", - "rtvFormat": "DXGI_FORMAT_R16G16_SINT" - } - ], - "GL_RG16UI": [ - { - "texFormat": "DXGI_FORMAT_R16G16_UINT", - "srvFormat": "DXGI_FORMAT_R16G16_UINT", - "rtvFormat": "DXGI_FORMAT_R16G16_UINT" - } - ], - "GL_RG32F": [ - { - "texFormat": "DXGI_FORMAT_R32G32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT" - } - ], - "GL_RG32I": [ - { - "texFormat": "DXGI_FORMAT_R32G32_SINT", - "srvFormat": "DXGI_FORMAT_R32G32_SINT", - "rtvFormat": "DXGI_FORMAT_R32G32_SINT" - } - ], - "GL_RG32UI": [ - { - "texFormat": "DXGI_FORMAT_R32G32_UINT", - "srvFormat": "DXGI_FORMAT_R32G32_UINT", - "rtvFormat": "DXGI_FORMAT_R32G32_UINT" - } - ], - "GL_RG8": [ - { - "texFormat": "DXGI_FORMAT_R8G8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8_UNORM" - } - ], - "GL_RG8I": [ - { - "texFormat": "DXGI_FORMAT_R8G8_SINT", - "srvFormat": "DXGI_FORMAT_R8G8_SINT", - "rtvFormat": "DXGI_FORMAT_R8G8_SINT" - } - ], - "GL_RG8UI": [ - { - "texFormat": "DXGI_FORMAT_R8G8_UINT", - "srvFormat": "DXGI_FORMAT_R8G8_UINT", - "rtvFormat": "DXGI_FORMAT_R8G8_UINT" - } - ], - "GL_RG8_SNORM": [ - { - "texFormat": "DXGI_FORMAT_R8G8_SNORM", - "srvFormat": "DXGI_FORMAT_R8G8_SNORM" - } - ], - "GL_RGB": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_RGB10_A2": [ - { - "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", - "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", - "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM" - } - ], - "GL_RGB10_A2UI": [ - { - "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT", - "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", - "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT" - } - ], - "GL_RGB16F": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - } - ], - "GL_RGB16I": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" - } - ], - "GL_RGB16UI": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" - } - ], - "GL_RGB32F": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - ], - "GL_RGB32I": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" - } - ], - "GL_RGB32UI": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" - } - ], - "GL_RGB565": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,false>" - }, - { - "texFormat": "DXGI_FORMAT_B5G6R5_UNORM", - "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM", - "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>" - } - ], - "GL_RGB5_A1": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,false>" - }, - { - "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", - "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", - "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>" - } - ], - "GL_RGB8": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_RGB8I": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" - } - ], - "GL_RGB8UI": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" - } - ], - "GL_RGB8_SNORM": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" - } - ], - "GL_RGB9_E5": [ - { - "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", - "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP" - } - ], - "GL_RGBA": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_RGBA16F": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" - } - ], - "GL_RGBA16I": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" - } - ], - "GL_RGBA16UI": [ - { - "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", - "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" - } - ], - "GL_RGBA32F": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" - } - ], - "GL_RGBA32I": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" - } - ], - "GL_RGBA32UI": [ - { - "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", - "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" - } - ], - "GL_RGBA4": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,false>" - }, - { - "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", - "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", - "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", - "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>" - } - ], - "GL_RGBA8": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" - } - ], - "GL_RGBA8I": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" - } - ], - "GL_RGBA8UI": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" - } - ], - "GL_RGBA8_SNORM": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" - } - ], - "GL_SRGB8": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB" - } - ], - "GL_SRGB8_ALPHA8": [ - { - "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", - "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB" - } - ], - "GL_STENCIL_INDEX8": [ - { - "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "srvFormat": "DXGI_FORMAT_X24_TYPELESS_G8_UINT", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL10Plus" + "FL9_3": { + "texFormat": "DXGI_FORMAT_D16_UNORM" }, - { - "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL9_3" - } - ] + "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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json new file mode 100644 index 0000000000..3ef2355645 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json @@ -0,0 +1,78 @@ +{ + "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT", + "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT", + "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA8_SRGB_ANGLEX": "B8G8R8A8_UNORM_SRGB", + "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_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_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_BLOCK", + "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_SRGB_BLOCK", + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_BLOCK", + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_SRGB_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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp new file mode 100644 index 0000000000..a9dfec56b8 --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h index 1606a28a73..3efcb81adb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h @@ -12,50 +12,91 @@ #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" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { -namespace d3d11 -{ +struct Renderer11DeviceCaps; -struct LoadImageFunctionInfo +namespace d3d11 { - LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {} - LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion) - : loadFunction(loadFunction), requiresConversion(requiresConversion) - { - } - - LoadImageFunction loadFunction; - bool requiresConversion; -}; -struct TextureFormat +// 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 : private angle::NonCopyable { - TextureFormat(); + 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 renderFormat; - DXGI_FORMAT swizzleTexFormat; - DXGI_FORMAT swizzleSRVFormat; - DXGI_FORMAT swizzleRTVFormat; + DXGI_FORMAT blitSRVFormat; - InitializeTextureDataFunction dataInitializerFunction; - typedef std::map<GLenum, LoadImageFunctionInfo> LoadFunctionMap; + GLenum swizzleFormat; - LoadFunctionMap loadFunctions; + InitializeTextureDataFunction dataInitializerFunction; }; -const TextureFormat &GetTextureFormatInfo(GLenum internalformat, - const Renderer11DeviceCaps &renderer11DeviceCaps); +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 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp index 0b214c9756..3c1c2bcd50 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp @@ -1,7 +1,7 @@ // GENERATED FILE - DO NOT EDIT. // Generated by gen_texture_format_table.py using data from texture_format_data.json // -// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Copyright 2017 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. // @@ -11,12 +11,15 @@ #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/internal_format_initializer_table.h" -#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h" -#include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" + +using namespace angle; namespace rx { @@ -24,1756 +27,1899 @@ namespace rx namespace d3d11 { -namespace -{ - -typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &); - -bool AnyDevice(const Renderer11DeviceCaps &deviceCaps) -{ - return true; -} - -bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps) -{ - return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0); -} - -bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps) -{ - return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3); -} - -template <DXGI_FORMAT format, bool requireSupport> -bool SupportsFormat(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 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below, - // which maps GL formats to DXGI formats. - if (requireSupport) - { - // 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; - } - else - { - // This means that ANGLE would like to use the entry in the map if the inputted DXGI format - // *ISN'T* supported. - // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if - // DXGI_FORMAT_B5G5R5A1 isn't supported. - // In this case, we should only return 'true' if the format *ISN'T* supported. - return !fullSupport; - } -} - -// End Format Support Functions - -// For sized GL internal formats, there are several possible corresponding D3D11 formats depending -// on device capabilities. -// This function allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and -// DSVs given a GL internal format. -const TextureFormat GetD3D11FormatInfo(GLenum internalFormat, - DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, - DXGI_FORMAT rtvFormat, - DXGI_FORMAT dsvFormat) -{ - TextureFormat info; - info.texFormat = texFormat; - info.srvFormat = srvFormat; - info.rtvFormat = rtvFormat; - info.dsvFormat = dsvFormat; - - // Given a GL internal format, the renderFormat is the DSV format if it is depth- or - // stencil-renderable, - // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. - if (dsvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = dsvFormat; - } - else if (rtvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = rtvFormat; - } - else if (texFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = texFormat; - } - else - { - info.renderFormat = DXGI_FORMAT_UNKNOWN; - } - - // Compute the swizzle formats - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) - { - if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || - srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) - { - // Get the maximum sized component - unsigned int maxBits = 1; - if (formatInfo.compressed) - { - unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; - unsigned int blockSize = - formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; - maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); - } - else - { - maxBits = std::max(maxBits, formatInfo.alphaBits); - maxBits = std::max(maxBits, formatInfo.redBits); - maxBits = std::max(maxBits, formatInfo.greenBits); - maxBits = std::max(maxBits, formatInfo.blueBits); - maxBits = std::max(maxBits, formatInfo.luminanceBits); - maxBits = std::max(maxBits, formatInfo.depthBits); - } - - maxBits = roundUp(maxBits, 8U); - - const SwizzleFormatInfo &swizzleInfo = - GetSwizzleFormatInfo(maxBits, formatInfo.componentType); - info.swizzleTexFormat = swizzleInfo.mTexFormat; - info.swizzleSRVFormat = swizzleInfo.mSRVFormat; - info.swizzleRTVFormat = swizzleInfo.mRTVFormat; - } - else - { - // The original texture format is suitable for swizzle operations - info.swizzleTexFormat = texFormat; - info.swizzleSRVFormat = srvFormat; - info.swizzleRTVFormat = rtvFormat; - } - } - else - { - // Not possible to swizzle with this texture format since it is either unsized or GL_NONE - info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; - } - - // Check if there is an initialization function for this texture format - info.dataInitializerFunction = GetInternalFormatInitializer(internalFormat, texFormat); - // Gather all the load functions for this internal format - info.loadFunctions = GetLoadFunctionsMap(internalFormat, texFormat); - - ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE); - - return info; -} - -} // namespace - -TextureFormat::TextureFormat() - : texFormat(DXGI_FORMAT_UNKNOWN), - srvFormat(DXGI_FORMAT_UNKNOWN), - rtvFormat(DXGI_FORMAT_UNKNOWN), - dsvFormat(DXGI_FORMAT_UNKNOWN), - renderFormat(DXGI_FORMAT_UNKNOWN), - swizzleTexFormat(DXGI_FORMAT_UNKNOWN), - swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), - swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), - dataInitializerFunction(NULL), - loadFunctions() -{ -} - -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, - const Renderer11DeviceCaps &renderer11DeviceCaps) +// static +const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) { // clang-format off switch (internalFormat) { - case GL_ALPHA: - { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (OnlyFL9_3(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } - } case GL_ALPHA16F_EXT: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (OnlyFL9_3(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + 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 { - break; + 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_BGR5_A1_ANGLEX: + case GL_BGR565_ANGLEX: { - if (AnyDevice(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + 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 { - break; + 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_BGRA4_ANGLEX: + case GL_BGR5_A1_ANGLEX: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_BGRA8_EXT: + case GL_BGRA4_ANGLEX: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_BGRA_EXT: + case GL_BGRA8_EXT: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_BGRA8_SRGB_ANGLEX: + { + static constexpr Format info(GL_BGRA8_SRGB_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + GL_BGRA8_SRGB_ANGLEX, + nullptr); + return info; } case GL_COMPRESSED_R11_EAC: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_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_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, + 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_RGBA8_ETC2_EAC: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_BC2_UNORM, - DXGI_FORMAT_BC2_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_BC3_UNORM, - DXGI_FORMAT_BC3_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_SNORM, - DXGI_FORMAT_R8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_SNORM, - DXGI_FORMAT_R8G8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; } case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: { - if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + angle::Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC2_UNORM_SRGB, + DXGI_FORMAT_BC2_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC2_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + angle::Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC3_UNORM_SRGB, + DXGI_FORMAT_BC3_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC3_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; } case GL_DEPTH24_STENCIL8: { - if (OnlyFL9_3(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R24G8_TYPELESS, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; + 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 { - break; + 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: { - if (OnlyFL9_3(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G8X24_TYPELESS, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT); - return textureFormat; - } - else - { - break; - } + 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 (OnlyFL9_3(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_D16_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D16_UNORM); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16_TYPELESS, - DXGI_FORMAT_R16_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D16_UNORM); - return textureFormat; + 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 { - break; + 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 (OnlyFL9_3(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R24G8_TYPELESS, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; + 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 { - break; + 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: { - if (OnlyFL9_3(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32_TYPELESS, - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D32_FLOAT); - return textureFormat; - } - else - { - break; - } + 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(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R24G8_TYPELESS, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; + 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 { - break; + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_BC1_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } - } - case GL_LUMINANCE: - { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } - } - case GL_LUMINANCE_ALPHA: - { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R11G11B10_FLOAT, - DXGI_FORMAT_R11G11B10_FLOAT, - DXGI_FORMAT_R11G11B10_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16_SINT, - DXGI_FORMAT_R16_SINT, - DXGI_FORMAT_R16_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16_UINT, - DXGI_FORMAT_R16_UINT, - DXGI_FORMAT_R16_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32_SINT, - DXGI_FORMAT_R32_SINT, - DXGI_FORMAT_R32_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32_UINT, - DXGI_FORMAT_R32_UINT, - DXGI_FORMAT_R32_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_R8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_SINT, - DXGI_FORMAT_R8_SINT, - DXGI_FORMAT_R8_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_UINT, - DXGI_FORMAT_R8_UINT, - DXGI_FORMAT_R8_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8_SNORM, - DXGI_FORMAT_R8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16_SINT, - DXGI_FORMAT_R16G16_SINT, - DXGI_FORMAT_R16G16_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16_UINT, - DXGI_FORMAT_R16G16_UINT, - DXGI_FORMAT_R16G16_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32_SINT, - DXGI_FORMAT_R32G32_SINT, - DXGI_FORMAT_R32G32_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32_UINT, - DXGI_FORMAT_R32G32_UINT, - DXGI_FORMAT_R32G32_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_R8G8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_SINT, - DXGI_FORMAT_R8G8_SINT, - DXGI_FORMAT_R8G8_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_UINT, - DXGI_FORMAT_R8G8_UINT, - DXGI_FORMAT_R8G8_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8_SNORM, - DXGI_FORMAT_R8G8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R10G10B10A2_UNORM, - DXGI_FORMAT_R10G10B10A2_UNORM, - DXGI_FORMAT_R10G10B10A2_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R10G10B10A2_UINT, - DXGI_FORMAT_R10G10B10A2_UINT, - DXGI_FORMAT_R10G10B10A2_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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,false>(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_B5G6R5_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + 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 { - break; + 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,false>(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + 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 { - break; + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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,false>(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B4G4R4A4_UNORM, - DXGI_FORMAT_B4G4R4A4_UNORM, - DXGI_FORMAT_B4G4R4A4_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + 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 { - break; + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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: { - if (AnyDevice(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - DXGI_FORMAT_UNKNOWN); - return textureFormat; - } - else - { - break; - } + 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 (OnlyFL9_3(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; - } - else if (OnlyFL10Plus(renderer11DeviceCaps)) - { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R24G8_TYPELESS, - DXGI_FORMAT_X24_TYPELESS_G8_UINT, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT); - return textureFormat; + 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 { - break; + 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; } } @@ -1782,9 +1928,10 @@ const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, } // clang-format on - static const TextureFormat defaultInfo; + UNREACHABLE(); + static constexpr Format defaultInfo; return defaultInfo; -} // GetTextureFormatInfo +} } // namespace d3d11 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h new file mode 100644 index 0000000000..d5351ff882 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h @@ -0,0 +1,85 @@ +// +// 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; + UINT minimumRequiredSamples = 0; + + if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel).major > 2) + { + mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + + // RGBA4, RGB5A1 and RGB565 are all required multisampled renderbuffer formats in ES3 and + // need to support a minimum of 4 samples. + minimumRequiredSamples = 4; + } + + 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) && + deviceCaps.B5G6R5maxSamples >= minimumRequiredSamples; + } + else if (format == DXGI_FORMAT_B4G4R4A4_UNORM) + { + fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport) && + deviceCaps.B4G4R4A4maxSamples >= minimumRequiredSamples; + } + else if (format == DXGI_FORMAT_B5G5R5A1_UNORM) + { + fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport) && + deviceCaps.B5G5R5A1maxSamples >= minimumRequiredSamples; + } + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp index da6460b136..5394e3d3e7 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp @@ -1,76 +1,70 @@ // -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// 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. // -// NativeWindow.cpp: Handler for managing HWND native window types. +// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs. -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "common/debug.h" #include <initguid.h> -#if !defined(__MINGW32__) #include <dcomp.h> -#endif namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, - const egl::Config *config, - bool directComposition) - : mWindow(window), +NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window, + bool hasAlpha, + bool directComposition) + : NativeWindow11(window), mDirectComposition(directComposition), + mHasAlpha(hasAlpha), mDevice(nullptr), mCompositionTarget(nullptr), - mVisual(nullptr), - mConfig(config) + mVisual(nullptr) { } -NativeWindow::~NativeWindow() +NativeWindow11Win32::~NativeWindow11Win32() { -#if !defined(__MINGW32__) SafeRelease(mCompositionTarget); SafeRelease(mDevice); SafeRelease(mVisual); -#endif } -bool NativeWindow::initialize() +bool NativeWindow11Win32::initialize() { return true; } -bool NativeWindow::getClientRect(LPRECT rect) +bool NativeWindow11Win32::getClientRect(LPRECT rect) const { - return GetClientRect(mWindow, rect) == TRUE; + return GetClientRect(getNativeWindow(), rect) == TRUE; } -bool NativeWindow::isIconic() +bool NativeWindow11Win32::isIconic() const { - return IsIconic(mWindow) == TRUE; + return IsIconic(getNativeWindow()) == TRUE; } -bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) +HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) { - return IsWindow(window) == TRUE; -} - -#if defined(ANGLE_ENABLE_D3D11) -HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, - DXGI_FORMAT format, unsigned int width, unsigned int height, - DXGISwapChain** swapChain) -{ - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) { return E_INVALIDARG; } -#if !defined(__MINGW32__) if (mDirectComposition) { HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll")); @@ -104,7 +98,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory if (!mCompositionTarget) { - HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget); + HRESULT result = + mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget); if (FAILED(result)) { return result; @@ -127,21 +122,21 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory swapChainDesc.Format = format; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; + 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.BufferCount = 2; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.AlphaMode = - mConfig->alphaSize == 0 ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED; + 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<DXGISwapChain *>(swapChain1); + *swapChain = static_cast<IDXGISwapChain *>(swapChain1); } mVisual->SetContent(swapChain1); mCompositionTarget->SetRoot(mVisual); @@ -149,72 +144,74 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory return result; } - // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a DXGI_SWAP_EFFECT_SEQUENTIAL swap chain. + // 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; + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = samples; + 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; + 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, mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1); + HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc, + nullptr, nullptr, &swapChain1); if (SUCCEEDED(result)) { - const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER); - UNUSED_VARIABLE(makeWindowAssociationResult); - *swapChain = static_cast<DXGISwapChain*>(swapChain1); + factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + *swapChain = static_cast<IDXGISwapChain *>(swapChain1); } SafeRelease(factory2); return result; } -#endif // !__MINGW32__ - - 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; + + 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 = mWindow; - swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = getNativeWindow(); + swapChainDesc.SampleDesc.Count = samples; swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.Windowed = TRUE; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - const HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); if (SUCCEEDED(result)) { - const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER); - UNUSED_VARIABLE(makeWindowAssociationResult); + factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); } return result; } -#endif -void NativeWindow::commitChange() +void NativeWindow11Win32::commitChange() { -#if !defined(__MINGW32__) if (mDevice) { mDevice->Commit(); } -#endif } + +// static +bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; } +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h new file mode 100644 index 0000000000..baeba6a347 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h @@ -0,0 +1,53 @@ +// +// 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, + UINT samples, + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp index f401db614b..1ef90e7b09 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp @@ -8,6 +8,8 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include <windows.graphics.display.h> + using namespace ABI::Windows::Foundation::Collections; namespace rx @@ -19,7 +21,6 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow() bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { - mOrientationChangedEventToken.value = 0; ComPtr<IPropertySet> props = propertySet; ComPtr<IInspectable> win = window; SIZE swapChainSize = {}; @@ -63,7 +64,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet // 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."); + ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a " + "EGLRenderResolutionScaleProperty."; return false; } } @@ -87,28 +89,18 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet } else { - SIZE coreWindowSize; + Size coreWindowSize; result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize); if (SUCCEEDED(result)) { - mClientRect = { 0, 0, static_cast<long>(coreWindowSize.cx * mSwapChainScale), static_cast<long>(coreWindowSize.cy * mSwapChainScale) }; + mClientRect = clientRect(coreWindowSize); } } } if (SUCCEEDED(result)) { - ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation; - result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation); - if (SUCCEEDED(result)) - { - result = displayInformation->GetForCurrentView(&mDisplayInformation); - } - } - - if (SUCCEEDED(result)) - { mNewClientRect = mClientRect; mClientRectChanged = false; return registerForSizeChangeEvents(); @@ -126,16 +118,6 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents() result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); } -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler; - result = sizeChangedHandler.As(&orientationChangedHandler); - if (SUCCEEDED(result)) - { - result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken); - orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr); - } -#endif - if (SUCCEEDED(result)) { return true; @@ -150,34 +132,26 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents() { (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); } - -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - if (mDisplayInformation) - { - (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken); - } -#endif - mSizeChangedEventToken.value = 0; - mOrientationChangedEventToken.value = 0; } HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) + IDXGISwapChain1 **swapChain) { - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) { return E_INVALIDARG; } DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; - swapChainDesc.Width = mRotationFlags ? height : width; - swapChainDesc.Height = mRotationFlags ? width : height; + swapChainDesc.Width = width; + swapChainDesc.Height = height; swapChainDesc.Format = format; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; @@ -195,17 +169,6 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); if (SUCCEEDED(result)) { - -#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain. - // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On - // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed - // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. - if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) - { - mSupportsSwapChainResize = false; - } -#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - result = newSwapChain.CopyTo(swapChain); } @@ -222,14 +185,16 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, return result; } -inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect) +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) +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow, + Size *windowSize) { ABI::Windows::Foundation::Rect bounds; HRESULT result = coreWindow->get_Bounds(&bounds); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h index fc1cd124a1..21855c2c3b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h @@ -12,10 +12,10 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" #include <memory> -#include <windows.graphics.display.h> + +#include <EGL/eglplatform.h> typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; -typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler; namespace rx { @@ -26,12 +26,12 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) override; + IDXGISwapChain1 **swapChain) override; protected: HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; @@ -42,13 +42,11 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl private: ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow; ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; - ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation; - EventRegistrationToken mOrientationChangedEventToken; }; [uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] class CoreWindowSizeChangedHandler : - public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler> + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler> { public: CoreWindowSizeChangedHandler() { } @@ -72,47 +70,21 @@ class CoreWindowSizeChangedHandler : ABI::Windows::Foundation::Size windowSize; if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) { - host->setNewClientSize(windowSize); + Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width), + ConvertDipsToPixels(windowSize.Height)}; + host->setNewClientSize(windowSizeInPixels); } } return S_OK; } - IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) - { - #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - NativeWindow::RotationFlags flags = NativeWindow::RotateNone; - ABI::Windows::Graphics::Display::DisplayOrientations orientation; - if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) - { - switch (orientation) - { - case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: - flags = NativeWindow::RotateLeft; - break; - case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: - flags = NativeWindow::RotateRight; - break; - default: - break; - } - } - std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); - if (host) - { - host->setRotationFlags(flags); - } - #endif - return S_OK; - } - - private: std::weak_ptr<InspectableNativeWindow> mHost; }; -HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, SIZE *windowSize); +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow, + Size *windowSize); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp index aacfadd2f0..1bd796e58f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -11,108 +11,6 @@ namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, - const egl::Config *config, - bool directComposition) -{ - mWindow = window; - mConfig = config; -} - -NativeWindow::~NativeWindow() -{ -} - -void NativeWindow::commitChange() -{ -} - -bool NativeWindow::initialize() -{ - // 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(mWindow, &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. - mWindow = eglNativeWindow.Get(); - } - - ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow; - ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel; - if (IsCoreWindow(mWindow, &coreWindow)) - { - mImpl = std::make_shared<CoreWindowNativeWindow>(); - if (mImpl) - { - return mImpl->initialize(mWindow, propertySet.Get()); - } - } - else if (IsSwapChainPanel(mWindow, &swapChainPanel)) - { - mImpl = std::make_shared<SwapChainPanelNativeWindow>(); - if (mImpl) - { - return mImpl->initialize(mWindow, propertySet.Get()); - } - } - else - { - ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); - } - - return false; -} - -bool NativeWindow::getClientRect(RECT *rect) -{ - if (mImpl) - { - return mImpl->getClientRect(rect); - } - - return false; -} - -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -NativeWindow::RotationFlags NativeWindow::rotationFlags() const -{ - if (mImpl) - { - return mImpl->rotationFlags(); - } - - return NativeWindow::RotateNone; -} -#endif - -bool NativeWindow::isIconic() -{ - return false; -} - -bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) -{ - return IsValidEGLNativeWindowType(window); -} - -HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) -{ - if (mImpl) - { - bool containsAlpha = (mConfig->alphaSize > 0); - return mImpl->createSwapChain(device, factory, format, width, height, containsAlpha, - swapChain); - } - - return E_UNEXPECTED; -} bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow) { @@ -127,7 +25,7 @@ bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICo { if (coreWindow != nullptr) { - *coreWindow = coreWin.Detach(); + *coreWindow = coreWin; } return true; } @@ -148,7 +46,7 @@ bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml: { if (swapChainPanel != nullptr) { - *swapChainPanel = panel.Detach(); + *swapChainPanel = panel; } return true; } @@ -185,7 +83,8 @@ bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Founda // considered invalid. if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) { - ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + ERR() << "Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid " + "EGLNativeWindowTypeProperty values include ICoreWindow"; return false; } @@ -219,18 +118,6 @@ bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Founda return false; } -// A Valid EGLNativeWindowType IInspectable can only be: -// -// ICoreWindow -// ISwapChainPanel -// IPropertySet -// -// Anything else will be rejected as an invalid IInspectable. -bool IsValidEGLNativeWindowType(EGLNativeWindowType window) -{ - return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); -} - // Retrieve an optional property from a property set HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap, const wchar_t *propertyName, @@ -381,7 +268,13 @@ HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Co return result; } -static float GetLogicalDpi() +RECT InspectableNativeWindow::clientRect(const Size &size) +{ + return {0, 0, static_cast<long>(ConvertDipsToPixels(size.Width)), + static_cast<long>(ConvertDipsToPixels(size.Height))}; +} + +float GetLogicalDpi() { ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties; float dpi = 96.0f; @@ -396,7 +289,7 @@ static float GetLogicalDpi() return dpi; } -long ConvertDipsToPixels(float dips) +float ConvertDipsToPixels(float dips) { static const float dipsPerInch = 96.0f; return lround((dips * GetLogicalDpi() / dipsPerInch)); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h index 2d58f1c00a..d81c3e5fb9 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h @@ -10,14 +10,18 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ #define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.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; @@ -26,7 +30,8 @@ using namespace ABI::Windows::Foundation::Collections; namespace rx { -long ConvertDipsToPixels(float dips); +float ConvertDipsToPixels(float dips); +float GetLogicalDpi(); class InspectableNativeWindow { @@ -35,24 +40,25 @@ class InspectableNativeWindow mSupportsSwapChainResize(true), mSwapChainSizeSpecified(false), mSwapChainScaleSpecified(false), - mSwapChainScale(1.0f), mClientRectChanged(false), mClientRect({0,0,0,0}), - mNewClientRect({0,0,0,0}), - mRotationFlags(NativeWindow::RotateNone) + mNewClientRect({0,0,0,0}) { mSizeChangedEventToken.value = 0; + mSwapChainScale = 96.0f / GetLogicalDpi(); + if (mSwapChainScale != 1.0f) + mSwapChainScaleSpecified = true; } virtual ~InspectableNativeWindow(){} virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; virtual HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) = 0; + IDXGISwapChain1 **swapChain) = 0; bool getClientRect(RECT *rect) { @@ -77,8 +83,7 @@ class InspectableNativeWindow // If the swapchain size was specified then we should ignore this call too if (!mSwapChainSizeSpecified) { - // We don't have to check if a swapchain scale was specified here; the default value is 1.0f which will have no effect. - mNewClientRect = { 0, 0, ConvertDipsToPixels(newWindowSize.Width), ConvertDipsToPixels(newWindowSize.Height) }; + 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 @@ -97,18 +102,9 @@ class InspectableNativeWindow } } - NativeWindow::RotationFlags rotationFlags() const - { - return mRotationFlags; - } - - void setRotationFlags(NativeWindow::RotationFlags flags) - { - mRotationFlags = flags; - } - 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 @@ -117,12 +113,10 @@ class InspectableNativeWindow RECT mClientRect; RECT mNewClientRect; bool mClientRectChanged; - NativeWindow::RotationFlags mRotationFlags; EventRegistrationToken mSizeChangedEventToken; }; -bool IsValidEGLNativeWindowType(EGLNativeWindowType window); 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); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp new file mode 100644 index 0000000000..655b23be83 --- /dev/null +++ b/src/3rdparty/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, + UINT samples, + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h new file mode 100644 index 0000000000..c4ac997a55 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h @@ -0,0 +1,51 @@ +// +// 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, + UINT samples, + 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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp index 548b4602fd..3425fad95d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp @@ -49,7 +49,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher) } else { - Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); + Event waitEvent( + CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); if (!waitEvent.IsValid()) { return E_FAIL; @@ -78,7 +79,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher) // 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."); + ERR() + << "Timeout waiting for async action on UI thread. The UI thread might be blocked."; std::terminate(); return E_FAIL; } @@ -132,7 +134,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert // 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."); + ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a " + "EGLRenderResolutionScaleProperty."; return false; } } @@ -169,17 +172,14 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert } else { - SIZE swapChainPanelSize; + Size swapChainPanelSize; result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, - &swapChainPanelSize, &mSwapChainScale); - if (mSwapChainScale != 1.0f) - mSwapChainScaleSpecified = true; + &swapChainPanelSize); if (SUCCEEDED(result)) { // Update the client rect to account for any swapchain scale factor - mClientRect = { 0, 0, static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cx * mSwapChainScale)), - static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cy * mSwapChainScale)) }; + mClientRect = clientRect(swapChainPanelSize); } } } @@ -241,14 +241,15 @@ void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() } HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) + IDXGISwapChain1 **swapChain) { - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) { return E_INVALIDARG; } @@ -272,6 +273,7 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, ComPtr<IDXGISwapChain1> newSwapChain; ComPtr<ISwapChainPanelNative> swapChainPanelNative; + Size currentPanelSize = {}; HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); @@ -306,14 +308,14 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, { if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) { - ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement; - result = mSwapChainPanel.As(&uiElement); - ASSERT(SUCCEEDED(result)); - - Size currentSize; - result = uiElement->get_RenderSize(¤tSize); - ASSERT(SUCCEEDED(result)); - result = scaleSwapChain(currentSize, mClientRect); + result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, + ¤tPanelSize); + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result)) + { + result = scaleSwapChain(currentPanelSize, mClientRect); + } } } @@ -342,31 +344,14 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const HRESULT GetSwapChainPanelSize( const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, const ComPtr<ICoreDispatcher> &dispatcher, - SIZE *windowSize, float *scaleFactor) + Size *windowSize) { ComPtr<IUIElement> uiElement; - Size renderSize = {0, 0}; HRESULT result = swapChainPanel.As(&uiElement); if (SUCCEEDED(result)) { result = RunOnUIThread( - [uiElement, &renderSize] - { - return uiElement->get_RenderSize(&renderSize); - }, - dispatcher); - } - - if (SUCCEEDED(result)) - { - long width = ConvertDipsToPixels(renderSize.Width); - long height = ConvertDipsToPixels(renderSize.Height); - *windowSize = { width, height }; - - if (scaleFactor) - { - *scaleFactor = renderSize.Width / width; - } + [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher); } return result; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h index 09d87ad523..f9a2fc0e4b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h @@ -11,6 +11,8 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" +#include <memory> + namespace rx { class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow> @@ -20,12 +22,12 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) override; + IDXGISwapChain1 **swapChain) override; protected: HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; @@ -37,7 +39,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel; ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher; ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; - ComPtr<DXGISwapChain> mSwapChain; + ComPtr<IDXGISwapChain1> mSwapChain; }; [uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] @@ -86,6 +88,6 @@ class SwapChainPanelSizeChangedHandler : HRESULT GetSwapChainPanelSize( const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher, - SIZE *windowSize, float *scaleFactor); + Size *windowSize); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp index 2ac8ee3a29..36f2bd0db8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -7,6 +7,8 @@ // Blit9.cpp: Surface copy utility class. #include "libANGLE/renderer/d3d/d3d9/Blit9.h" + +#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" @@ -20,27 +22,34 @@ 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/luminancepremultps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h" #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h" -const BYTE* const g_shaderCode[] = -{ +const BYTE *const g_shaderCode[] = { g_vs20_standardvs, - g_vs20_flipyvs, g_ps20_passthroughps, g_ps20_luminanceps, - g_ps20_componentmaskps + g_ps20_luminancepremultps, + g_ps20_luminanceunmultps, + g_ps20_componentmaskps, + g_ps20_componentmaskpremultps, + g_ps20_componentmaskunmultps, }; -const size_t g_shaderSize[] = -{ +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) + sizeof(g_ps20_luminancepremultps), + sizeof(g_ps20_luminanceunmultps), + sizeof(g_ps20_componentmaskps), + sizeof(g_ps20_componentmaskpremultps), + sizeof(g_ps20_componentmaskunmultps), }; } @@ -50,11 +59,11 @@ namespace rx Blit9::Blit9(Renderer9 *renderer) : mRenderer(renderer), mGeometryLoaded(false), - mQuadVertexBuffer(NULL), - mQuadVertexDeclaration(NULL), - mSavedStateBlock(NULL), - mSavedRenderTarget(NULL), - mSavedDepthStencil(NULL) + mQuadVertexBuffer(nullptr), + mQuadVertexDeclaration(nullptr), + mSavedStateBlock(nullptr), + mSavedRenderTarget(nullptr), + mSavedDepthStencil(nullptr) { memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); } @@ -75,7 +84,7 @@ gl::Error Blit9::initialize() { if (mGeometryLoaded) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } static const float quad[] = @@ -88,22 +97,25 @@ gl::Error Blit9::initialize() IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); + HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, + D3DPOOL_DEFAULT, &mQuadVertexBuffer, nullptr); 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); + return gl::OutOfMemory() << "Failed to create internal blit vertex shader, " + << gl::FmtHR(result); } - void *lockPtr = NULL; + void *lockPtr = nullptr; result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); - if (FAILED(result) || lockPtr == NULL) + if (FAILED(result) || lockPtr == nullptr) { 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); + return gl::OutOfMemory() << "Failed to lock internal blit vertex shader, " + << gl::FmtHR(result); } memcpy(lockPtr, quad, sizeof(quad)); @@ -121,11 +133,12 @@ gl::Error Blit9::initialize() { 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); + return gl::OutOfMemory() << "Failed to lock internal blit vertex declaration, " + << gl::FmtHR(result); } mGeometryLoaded = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } template <class D3DShaderType> @@ -137,7 +150,7 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile, D3DShaderType *shader = nullptr; - if (mCompiledShaders[source] != NULL) + if (mCompiledShaders[source] != nullptr) { shader = static_cast<D3DShaderType*>(mCompiledShaders[source]); } @@ -145,23 +158,17 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile, { const BYTE* shaderCode = g_shaderCode[source]; size_t shaderSize = g_shaderSize[source]; - - gl::Error error = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader); - if (error.isError()) - { - return error; - } - + 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::OutOfMemory() << "Failed to set shader for blit operation, " << gl::FmtHR(hr); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Blit9::setVertexShader(ShaderId shader) @@ -188,20 +195,20 @@ RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const return rect; } +gl::Extents Blit9::getSurfaceSize(IDirect3DSurface9 *surface) const +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + return gl::Extents(desc.Width, desc.Height, 1); +} + gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initialize()); - IDirect3DTexture9 *texture = NULL; - error = copySurfaceToTexture(source, getSurfaceRect(source), &texture); - if (error.isError()) - { - return error; - } + IDirect3DBaseTexture9 *texture = nullptr; + ANGLE_TRY(copySurfaceToTexture(source, getSurfaceRect(source), &texture)); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -210,14 +217,15 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) device->SetTexture(0, texture); device->SetRenderTarget(0, dest); - setVertexShader(SHADER_VS_STANDARD); - setPixelShader(SHADER_PS_PASSTHROUGH); + ANGLE_TRY(setVertexShader(SHADER_VS_STANDARD)); + ANGLE_TRY(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)); + setViewportAndShaderConstants(getSurfaceRect(source), getSurfaceSize(source), + getSurfaceRect(dest), false); render(); @@ -225,34 +233,32 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) restoreState(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) +gl::Error Blit9::copy2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) { - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initialize()); const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); ASSERT(colorbuffer); RenderTarget9 *renderTarget9 = nullptr; - error = colorbuffer->getRenderTarget(&renderTarget9); - if (error.isError()) - { - return error; - } + ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget9)); ASSERT(renderTarget9); IDirect3DSurface9 *source = renderTarget9->getSurface(); ASSERT(source); - IDirect3DSurface9 *destSurface = NULL; + IDirect3DSurface9 *destSurface = nullptr; TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); - error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface); + gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, true, &destSurface); if (error.isError()) { SafeRelease(source); @@ -260,7 +266,8 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe } ASSERT(destSurface); - gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + gl::Error result = + copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false); SafeRelease(destSurface); SafeRelease(source); @@ -268,7 +275,14 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe 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 Blit9::copyCube(const gl::Context *context, + 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()) @@ -280,7 +294,7 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source ASSERT(colorbuffer); RenderTarget9 *renderTarget9 = nullptr; - error = colorbuffer->getRenderTarget(&renderTarget9); + error = colorbuffer->getRenderTarget(context, &renderTarget9); if (error.isError()) { return error; @@ -290,9 +304,9 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source IDirect3DSurface9 *source = renderTarget9->getSurface(); ASSERT(source); - IDirect3DSurface9 *destSurface = NULL; + IDirect3DSurface9 *destSurface = nullptr; TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); - error = storage9->getSurfaceLevel(target, level, true, &destSurface); + error = storage9->getSurfaceLevel(context, target, level, true, &destSurface); if (error.isError()) { SafeRelease(source); @@ -300,7 +314,8 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source } ASSERT(destSurface); - gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + gl::Error result = + copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false); SafeRelease(destSurface); SafeRelease(source); @@ -308,9 +323,69 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source return result; } -gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) +gl::Error Blit9::copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha) +{ + ANGLE_TRY(initialize()); + + const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); + + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(context, &sourceStorage)); + + TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage); + ASSERT(sourceStorage9); + + TextureStorage9 *destStorage9 = GetAs<TextureStorage9>(storage); + ASSERT(destStorage9); + + ASSERT(sourceLevel == 0); + IDirect3DBaseTexture9 *sourceTexture = nullptr; + ANGLE_TRY(sourceStorage9->getBaseTexture(context, &sourceTexture)); + + IDirect3DSurface9 *sourceSurface = nullptr; + ANGLE_TRY( + sourceStorage9->getSurfaceLevel(context, GL_TEXTURE_2D, sourceLevel, true, &sourceSurface)); + + IDirect3DSurface9 *destSurface = nullptr; + gl::Error error = + destStorage9->getSurfaceLevel(context, destTarget, destLevel, true, &destSurface); + if (error.isError()) + { + SafeRelease(sourceSurface); + return error; + } + + error = copy(sourceSurface, sourceTexture, sourceRect, destFormat, destOffset, destSurface, + flipY, premultiplyAlpha, unmultiplyAlpha); + + SafeRelease(sourceSurface); + SafeRelease(destSurface); + + return error; +} + +gl::Error Blit9::copy(IDirect3DSurface9 *source, + IDirect3DBaseTexture9 *sourceTexture, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + IDirect3DSurface9 *dest, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha) { - ASSERT(source != NULL && dest != NULL); + ASSERT(source != nullptr && dest != nullptr); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -319,8 +394,10 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum source->GetDesc(&sourceDesc); dest->GetDesc(&destDesc); - if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect + // Check if it's possible to use StetchRect + if (sourceDesc.Format == destDesc.Format && (destDesc.Usage & D3DUSAGE_RENDERTARGET) && + d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat) && !flipY && + premultiplyAlpha == unmultiplyAlpha) { 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); @@ -328,85 +405,135 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum 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::OutOfMemory() + << "Failed to blit between textures, StretchRect " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } else { - return formatConvert(source, sourceRect, destFormat, destOffset, dest); - } -} + IDirect3DBaseTexture9 *texture = sourceTexture; + RECT adjustedSourceRect = sourceRect; + gl::Extents sourceSize(sourceDesc.Width, sourceDesc.Height, 1); -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; - } + if (texture == nullptr) + { + ANGLE_TRY(copySurfaceToTexture(source, sourceRect, &texture)); + + // copySurfaceToTexture only copies in the sourceRect area of the source surface. + // Adjust sourceRect so that it is now covering the entire source texture + adjustedSourceRect.left = 0; + adjustedSourceRect.right = sourceRect.right - sourceRect.left; + adjustedSourceRect.top = 0; + adjustedSourceRect.bottom = sourceRect.bottom - sourceRect.top; + + sourceSize.width = sourceRect.right - sourceRect.left; + sourceSize.height = sourceRect.bottom - sourceRect.top; + } + else + { + texture->AddRef(); + } + + gl::Error error = formatConvert(texture, adjustedSourceRect, sourceSize, destFormat, + destOffset, dest, flipY, premultiplyAlpha, unmultiplyAlpha); + + SafeRelease(texture); - IDirect3DTexture9 *texture = NULL; - error = copySurfaceToTexture(source, sourceRect, &texture); - if (error.isError()) - { return error; } +} + +gl::Error Blit9::formatConvert(IDirect3DBaseTexture9 *source, + const RECT &sourceRect, + const gl::Extents &sourceSize, + GLenum destFormat, + const gl::Offset &destOffset, + IDirect3DSurface9 *dest, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha) +{ + ANGLE_TRY(initialize()); IDirect3DDevice9 *device = mRenderer->getDevice(); saveState(); - device->SetTexture(0, texture); + device->SetTexture(0, source); device->SetRenderTarget(0, dest); - setViewport(sourceRect, destOffset); + RECT destRect; + destRect.left = destOffset.x; + destRect.right = destOffset.x + (sourceRect.right - sourceRect.left); + destRect.top = destOffset.y; + destRect.bottom = destOffset.y + (sourceRect.bottom - sourceRect.top); + + setViewportAndShaderConstants(sourceRect, sourceSize, destRect, flipY); setCommonBlitState(); - error = setFormatConvertShaders(destFormat); + gl::Error error = setFormatConvertShaders(destFormat, flipY, premultiplyAlpha, unmultiplyAlpha); if (!error.isError()) { render(); } - SafeRelease(texture); - restoreState(); return error; } -gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) +gl::Error Blit9::setFormatConvertShaders(GLenum destFormat, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha) { - gl::Error error = setVertexShader(SHADER_VS_STANDARD); - if (error.isError()) - { - return error; - } + ANGLE_TRY(setVertexShader(SHADER_VS_STANDARD)); 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; + if (premultiplyAlpha == unmultiplyAlpha) + { + ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK)); + } + else if (premultiplyAlpha) + { + ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA)); + } + else + { + ASSERT(unmultiplyAlpha); + ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA)); + } + break; case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: - error = setPixelShader(SHADER_PS_LUMINANCE); - break; - } - - if (error.isError()) - { - return error; + if (premultiplyAlpha == unmultiplyAlpha) + { + ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE)); + } + else if (premultiplyAlpha) + { + ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA)); + } + else + { + ASSERT(unmultiplyAlpha); + ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA)); + } + break; + + default: + UNREACHABLE(); } enum { X = 0, Y = 1, Z = 2, W = 3 }; @@ -502,10 +629,12 @@ gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture) +gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, + const RECT &sourceRect, + IDirect3DBaseTexture9 **outTexture) { ASSERT(surface); @@ -516,12 +645,15 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so // Copy the render target into a texture IDirect3DTexture9 *texture; - HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); + HRESULT result = device->CreateTexture( + sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, + D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, nullptr); 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); + return gl::OutOfMemory() << "Failed to allocate internal texture for blit, " + << gl::FmtHR(result); } IDirect3DSurface9 *textureSurface; @@ -531,11 +663,12 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so { 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); + return gl::OutOfMemory() << "Failed to query surface of internal blit texture, " + << gl::FmtHR(result); } mRenderer->endScene(); - result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); + result = device->StretchRect(surface, &sourceRect, textureSurface, nullptr, D3DTEXF_NONE); SafeRelease(textureSurface); @@ -543,35 +676,50 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so { 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); + return gl::OutOfMemory() << "Failed to copy between internal blit textures, " + << gl::FmtHR(result); } *outTexture = texture; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset) +void Blit9::setViewportAndShaderConstants(const RECT &sourceRect, + const gl::Extents &sourceSize, + const RECT &destRect, + bool flipY) { 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.X = destRect.left; + vp.Y = destRect.top; + vp.Width = destRect.right - destRect.left; + vp.Height = destRect.bottom - destRect.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); + float vertexConstants[8] = { + // halfPixelAdjust + -1.0f / vp.Width, 1.0f / vp.Height, 0, 0, + // texcoordOffset + static_cast<float>(sourceRect.left) / sourceSize.width, + static_cast<float>(flipY ? sourceRect.bottom : sourceRect.top) / sourceSize.height, + static_cast<float>(sourceRect.right - sourceRect.left) / sourceSize.width, + static_cast<float>(flipY ? sourceRect.top - sourceRect.bottom + : sourceRect.bottom - sourceRect.top) / + sourceSize.height, + }; + + device->SetVertexShaderConstantF(0, vertexConstants, 2); } void Blit9::setCommonBlitState() { IDirect3DDevice9 *device = mRenderer->getDevice(); - device->SetDepthStencilSurface(NULL); + device->SetDepthStencilSurface(nullptr); device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); @@ -617,7 +765,7 @@ void Blit9::saveState() device->GetDepthStencilSurface(&mSavedDepthStencil); device->GetRenderTarget(0, &mSavedRenderTarget); - if (mSavedStateBlock == NULL) + if (mSavedStateBlock == nullptr) { hr = device->BeginStateBlock(); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); @@ -626,9 +774,9 @@ void Blit9::saveState() static const float dummyConst[8] = { 0 }; - device->SetVertexShader(NULL); + device->SetVertexShader(nullptr); device->SetVertexShaderConstantF(0, dummyConst, 2); - device->SetPixelShader(NULL); + device->SetPixelShader(nullptr); device->SetPixelShaderConstantF(0, dummyConst, 2); D3DVIEWPORT9 dummyVp; @@ -641,7 +789,7 @@ void Blit9::saveState() device->SetViewport(&dummyVp); - device->SetTexture(0, NULL); + device->SetTexture(0, nullptr); device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); @@ -651,9 +799,9 @@ void Blit9::saveState() ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); } - ASSERT(mSavedStateBlock != NULL); + ASSERT(mSavedStateBlock != nullptr); - if (mSavedStateBlock != NULL) + if (mSavedStateBlock != nullptr) { hr = mSavedStateBlock->Capture(); ASSERT(SUCCEEDED(hr)); @@ -670,9 +818,9 @@ void Blit9::restoreState() device->SetRenderTarget(0, mSavedRenderTarget); SafeRelease(mSavedRenderTarget); - ASSERT(mSavedStateBlock != NULL); + ASSERT(mSavedStateBlock != nullptr); - if (mSavedStateBlock != NULL) + if (mSavedStateBlock != nullptr) { mSavedStateBlock->Apply(); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h index 586abd2580..026874f8ae 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h @@ -16,7 +16,10 @@ namespace gl { +class Context; class Framebuffer; +class Texture; +struct Extents; struct Offset; } @@ -35,13 +38,33 @@ class Blit9 : angle::NonCopyable // 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); + gl::Error copy2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level); + gl::Error copyCube(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level); + gl::Error copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha); // 2x2 box filter sample from source to dest. // Requires that source is RGB(A) and dest has the same format as source. @@ -54,23 +77,56 @@ class Blit9 : angle::NonCopyable 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); + // Copy from source texture 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(IDirect3DBaseTexture9 *source, + const RECT &sourceRect, + const gl::Extents &sourceSize, + GLenum destFormat, + const gl::Offset &destOffset, + IDirect3DSurface9 *dest, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha); + gl::Error setFormatConvertShaders(GLenum destFormat, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha); + + gl::Error copy(IDirect3DSurface9 *source, + IDirect3DBaseTexture9 *sourceTexture, + const RECT &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + IDirect3DSurface9 *dest, + bool flipY, + bool premultiplyAlpha, + bool unmultiplyAlpha); + gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, + const RECT &sourceRect, + IDirect3DBaseTexture9 **outTexture); + void setViewportAndShaderConstants(const RECT &sourceRect, + const gl::Extents &sourceSize, + const RECT &destRect, + bool flipY); void setCommonBlitState(); RECT getSurfaceRect(IDirect3DSurface9 *surface) const; + gl::Extents getSurfaceSize(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_LUMINANCE_PREMULTIPLY_ALPHA, + SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA, SHADER_PS_COMPONENTMASK, - SHADER_COUNT + SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA, + SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA, + SHADER_COUNT, }; // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp index 804b6971ce..dc308e7752 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -12,23 +12,37 @@ namespace rx { -Buffer9::Buffer9(Renderer9 *renderer) - : BufferD3D(renderer), - mSize(0) -{} +Buffer9::Buffer9(const gl::BufferState &state, Renderer9 *renderer) + : BufferD3D(state, renderer), mSize(0) +{ +} Buffer9::~Buffer9() { mSize = 0; } -gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) +size_t Buffer9::getSize() const +{ + return mSize; +} + +bool Buffer9::supportsDirectBinding() const +{ + return false; +} + +gl::Error Buffer9::setData(const gl::Context *context, + gl::BufferBinding /*target*/, + const void *data, + size_t size, + gl::BufferUsage usage) { if (size > mMemory.size()) { if (!mMemory.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); + return gl::OutOfMemory() << "Failed to resize internal buffer."; } } @@ -38,25 +52,30 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) memcpy(mMemory.data(), data, size); } - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + updateD3DBufferUsage(context, usage); - updateD3DBufferUsage(usage); - return gl::Error(GL_NO_ERROR); + invalidateStaticData(context); + + return gl::NoError(); } -gl::Error Buffer9::getData(const uint8_t **outData) +gl::Error Buffer9::getData(const gl::Context *context, const uint8_t **outData) { *outData = mMemory.data(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) +gl::Error Buffer9::setSubData(const gl::Context *context, + gl::BufferBinding /*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."); + return gl::OutOfMemory() << "Failed to resize internal buffer."; } } @@ -66,46 +85,55 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) memcpy(mMemory.data() + offset, data, size); } - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +gl::Error Buffer9::copySubData(const gl::Context *context, + BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) { // Note: this method is currently unreachable - Buffer9* sourceBuffer = GetAs<Buffer9>(source); + Buffer9 *sourceBuffer = GetAs<Buffer9>(source); ASSERT(sourceBuffer); memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // We do not support buffer mapping in D3D9 -gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr) +gl::Error Buffer9::map(const gl::Context *context, GLenum access, void **mapPtr) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer9::mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error Buffer9::unmap(GLboolean *result) +gl::Error Buffer9::unmap(const gl::Context *context, GLboolean *result) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -void Buffer9::markTransformFeedbackUsage() +gl::Error Buffer9::markTransformFeedbackUsage(const gl::Context *context) { UNREACHABLE(); + return gl::InternalError(); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h index 44a524ba28..960b2a2474 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -20,28 +20,44 @@ class Renderer9; class Buffer9 : public BufferD3D { public: - Buffer9(Renderer9 *renderer); - virtual ~Buffer9(); + Buffer9(const gl::BufferState &state, Renderer9 *renderer); + ~Buffer9() override; // BufferD3D implementation - virtual size_t getSize() const { return mSize; } - virtual bool supportsDirectBinding() const { return false; } - gl::Error getData(const uint8_t **outData) override; + size_t getSize() const override; + bool supportsDirectBinding() const override; + gl::Error getData(const gl::Context *context, const uint8_t **outData) override; // BufferImpl implementation - virtual gl::Error setData(const void* data, size_t size, GLenum usage); - virtual gl::Error setSubData(const void* data, size_t size, size_t offset); - virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(GLenum access, GLvoid **mapPtr); - virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(GLboolean *result); - virtual void markTransformFeedbackUsage(); + gl::Error setData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + gl::BufferUsage usage) override; + gl::Error setSubData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + size_t offset) override; + gl::Error copySubData(const gl::Context *context, + BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) override; + gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override; + gl::Error mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) override; + gl::Error unmap(const gl::Context *context, GLboolean *result) override; + gl::Error markTransformFeedbackUsage(const gl::Context *context) override; private: - MemoryBuffer mMemory; + angle::MemoryBuffer mMemory; size_t mSize; }; -} +} // namespace rx -#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp new file mode 100644 index 0000000000..1b9874cc20 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp @@ -0,0 +1,303 @@ +// +// 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/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.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(), mRenderer->getNativeExtensions()); +} + +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); +} + +SyncImpl *Context9::createSync() +{ + // 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(const gl::SamplerState &state) +{ + return new SamplerD3D(state); +} + +ProgramPipelineImpl *Context9::createProgramPipeline(const gl::ProgramPipelineState &data) +{ + UNREACHABLE(); + return nullptr; +} + +std::vector<PathImpl *> Context9::createPaths(GLsizei) +{ + return std::vector<PathImpl *>(); +} + +gl::Error Context9::flush(const gl::Context *context) +{ + return mRenderer->flush(); +} + +gl::Error Context9::finish(const gl::Context *context) +{ + return mRenderer->finish(); +} + +gl::Error Context9::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) +{ + return mRenderer->genericDrawArrays(context, mode, first, count, 0); +} + +gl::Error Context9::drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount); +} + +gl::Error Context9::drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) +{ + return mRenderer->genericDrawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context9::drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) +{ + return mRenderer->genericDrawElements(context, mode, count, type, indices, instances); +} + +gl::Error Context9::drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) +{ + return mRenderer->genericDrawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context9::drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) +{ + UNREACHABLE(); + return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawArraysIndirect API"; +} + +gl::Error Context9::drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) +{ + UNREACHABLE(); + return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawElementsIndirect API"; +} + +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::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) +{ + // Fall through to the EXT_debug_marker functions + pushGroupMarker(length, message); +} + +void Context9::popDebugGroup() +{ + // Fall through to the EXT_debug_marker functions + popGroupMarker(); +} + +void Context9::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(mState.getState(), dirtyBits); +} + +GLint Context9::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 Context9::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void Context9::onMakeCurrent(const gl::Context *context) +{ +} + +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(); +} + +gl::Error Context9::dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + UNREACHABLE(); + return gl::InternalError() << "D3D9 doesn't support ES 3.1 DispatchCompute API"; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h new file mode 100644 index 0000000000..d681bfde89 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h @@ -0,0 +1,151 @@ +// +// 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; + SyncImpl *createSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler(const gl::SamplerState &state) override; + + // Program Pipeline object creation + ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override; + + // Path object creation + std::vector<PathImpl *> createPaths(GLsizei) override; + + // Flush and finish. + gl::Error flush(const gl::Context *context) override; + gl::Error finish(const gl::Context *context) override; + + // Drawing methods. + gl::Error drawArrays(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count) override; + gl::Error drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) override; + gl::Error drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) override; + gl::Error drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // EXT_debug_marker + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // KHR_debug + void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override; + void popDebugGroup() override; + + // State sync with dirty bits. + void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::Context *context) 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; + + gl::Error dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) override; + + Renderer9 *getRenderer() const { return mRenderer; } + + private: + Renderer9 *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h index 54e3bb9490..b28008335f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h @@ -9,12 +9,12 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ #define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ -#include "common/debug.h" +#include "libANGLE/LoggingAnnotator.h" namespace rx { -class DebugAnnotator9 : public gl::DebugAnnotator +class DebugAnnotator9 : public angle::LoggingAnnotator { public: DebugAnnotator9() {} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp index 3300681277..bff3881655 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp @@ -13,10 +13,7 @@ namespace rx { -FenceNV9::FenceNV9(Renderer9 *renderer) - : FenceNVImpl(), - mRenderer(renderer), - mQuery(NULL) +FenceNV9::FenceNV9(Renderer9 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr) { } @@ -41,10 +38,10 @@ gl::Error FenceNV9::set(GLenum condition) { 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::OutOfMemory() << "Failed to end event query, " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error FenceNV9::test(GLboolean *outFinished) @@ -66,7 +63,7 @@ gl::Error FenceNV9::finish() Sleep(0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished) @@ -74,21 +71,21 @@ gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished) ASSERT(mQuery); DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); - HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); + HRESULT result = mQuery->GetData(nullptr, 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."); + return gl::OutOfMemory() << "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); + return gl::OutOfMemory() << "Failed to get query data, " << gl::FmtHR(result); } ASSERT(result == S_OK || result == S_FALSE); *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h index 200ac68d27..de0ff20774 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h @@ -10,7 +10,7 @@ #define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ #include "libANGLE/renderer/FenceNVImpl.h" -#include "libANGLE/renderer/FenceSyncImpl.h" +#include "libANGLE/renderer/SyncImpl.h" namespace rx { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp index 9c269a8565..dff12e03f8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -7,21 +7,25 @@ // Framebuffer9.cpp: Implements the Framebuffer9 class. #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" -#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" -#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" -#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" -#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" -#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/formatutils.h" + +#include "libANGLE/Context.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/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/renderer_utils.h" namespace rx { -Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer) +Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer) : FramebufferD3D(data, renderer), mRenderer(renderer) { ASSERT(mRenderer != nullptr); @@ -31,66 +35,61 @@ Framebuffer9::~Framebuffer9() { } -gl::Error Framebuffer9::discard(size_t, const GLenum *) +gl::Error Framebuffer9::discard(const gl::Context *context, size_t, const GLenum *) { // Extension not implemented in D3D9 renderer UNREACHABLE(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer9::invalidate(size_t, const GLenum *) +gl::Error Framebuffer9::invalidate(const gl::Context *context, size_t, const GLenum *) { // Shouldn't ever reach here in D3D9 UNREACHABLE(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +gl::Error Framebuffer9::invalidateSub(const gl::Context *context, + size_t, + const GLenum *, + const gl::Rectangle &) { // Shouldn't ever reach here in D3D9 UNREACHABLE(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams) +gl::Error Framebuffer9::clearImpl(const gl::Context *context, const ClearParameters &clearParams) { - const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0); - const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment(); + const gl::FramebufferAttachment *colorAttachment = mState.getColorAttachment(0); + const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment(); - gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment)); - float nearZ = data.state->getNearPlane(); - float farZ = data.state->getFarPlane(); - mRenderer->setViewport(data.caps, data.state->getViewport(), nearZ, farZ, GL_TRIANGLES, - data.state->getRasterizerState().frontFace, true); + 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(data.state->getScissor(), data.state->isScissorTestEnabled()); + mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); - return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); + return mRenderer->clear(context, clearParams, colorAttachment, depthStencilAttachment); } -gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, +gl::Error Framebuffer9::readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const + uint8_t *pixels) { - ASSERT(pack.pixelBuffer.get() == nullptr); - - const gl::FramebufferAttachment *colorbuffer = mData.getColorAttachment(0); + const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0); ASSERT(colorbuffer); RenderTarget9 *renderTarget = nullptr; - gl::Error error = colorbuffer->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget)); ASSERT(renderTarget); IDirect3DSurface9 *surface = renderTarget->getSurface(); @@ -103,7 +102,8 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, { 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."); + return gl::OutOfMemory() + << "ReadPixels is unimplemented for multisampled framebuffer attachments."; } IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -135,7 +135,7 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); + return gl::OutOfMemory() << "Failed to allocate internal texture for ReadPixels."; } } @@ -157,13 +157,13 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, UNREACHABLE(); } - return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); + return gl::OutOfMemory() << "Failed to read internal render target data."; } if (directToPixels) { SafeRelease(systemSurface); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } RECT rect; @@ -180,85 +180,42 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, UNREACHABLE(); SafeRelease(systemSurface); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); + return gl::OutOfMemory() << "Failed to lock internal render target."; } - uint8_t *source; - int inputPitch; - if (pack.reverseRowOrder) - { - source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = reinterpret_cast<uint8_t*>(lock.pBits); - inputPitch = lock.Pitch; - } + uint8_t *source = reinterpret_cast<uint8_t *>(lock.pBits); + int inputPitch = lock.Pitch; const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); - if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) - { - // Direct copy possible - for (int y = 0; y < rect.bottom - rect.top; y++) - { - memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); - } - } - else - { - const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); - - GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + gl::FormatType formatType(format, type); - fastCopyFunc(src, dest); - } - } - } - else - { - ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction; - ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type); + 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; - uint8_t temp[sizeof(gl::ColorF)]; - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - colorReadFunction(src, temp); - colorWriteFunction(temp, dest); - } - } - } - } + PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels); systemSurface->UnlockRect(); SafeRelease(systemSurface); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, - bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, - const gl::Framebuffer *sourceFramebuffer) +gl::Error Framebuffer9::blitImpl(const gl::Context *context, + 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); @@ -273,18 +230,18 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl ASSERT(readBuffer); RenderTarget9 *readRenderTarget = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); + gl::Error error = readBuffer->getRenderTarget(context, &readRenderTarget); if (error.isError()) { return error; } ASSERT(readRenderTarget); - const gl::FramebufferAttachment *drawBuffer = mData.getColorAttachment(0); + const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0); ASSERT(drawBuffer); RenderTarget9 *drawRenderTarget = nullptr; - error = drawBuffer->getRenderTarget(&drawRenderTarget); + error = drawBuffer->getRenderTarget(context, &drawRenderTarget); if (error.isError()) { return error; @@ -389,7 +346,7 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + return gl::OutOfMemory() << "Internal blit failed, StretchRect " << gl::FmtHR(result); } } @@ -399,18 +356,18 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl ASSERT(readBuffer); RenderTarget9 *readDepthStencil = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readDepthStencil); + gl::Error error = readBuffer->getRenderTarget(context, &readDepthStencil); if (error.isError()) { return error; } ASSERT(readDepthStencil); - const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); ASSERT(drawBuffer); RenderTarget9 *drawDepthStencil = nullptr; - error = drawBuffer->getRenderTarget(&drawDepthStencil); + error = drawBuffer->getRenderTarget(context, &drawDepthStencil); if (error.isError()) { return error; @@ -431,18 +388,24 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + return gl::OutOfMemory() << "Internal blit failed, StretchRect " << gl::FmtHR(result); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const { RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget); const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat()); - return d3dFormatInfo.internalFormat; + return d3dFormatInfo.info().glInternalFormat; } +gl::Error Framebuffer9::getSamplePosition(size_t index, GLfloat *xy) const +{ + UNREACHABLE(); + return gl::InternalError() << "getSamplePosition is unsupported to d3d9."; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h index fe12079ae0..d2b46435ee 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -18,26 +18,40 @@ class Renderer9; class Framebuffer9 : public FramebufferD3D { public: - Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer); - virtual ~Framebuffer9(); + Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer); + ~Framebuffer9() override; - 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; + gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override; + gl::Error invalidate(const gl::Context *context, + size_t count, + const GLenum *attachments) override; + gl::Error invalidateSub(const gl::Context *context, + size_t count, + const GLenum *attachments, + const gl::Rectangle &area) override; + + gl::Error getSamplePosition(size_t index, GLfloat *xy) const override; private: - gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override; - gl::Error readPixelsImpl(const gl::Rectangle &area, + gl::Error readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const override; - - gl::Error blit(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; + uint8_t *pixels) override; + + gl::Error blitImpl(const gl::Context *context, + 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; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp index fec7e3e19d..179629b362 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -24,8 +24,8 @@ namespace rx Image9::Image9(Renderer9 *renderer) { - mSurface = NULL; - mRenderer = NULL; + mSurface = nullptr; + mRenderer = nullptr; mD3DPool = D3DPOOL_SYSTEMMEM; mD3DFormat = D3DFMT_UNKNOWN; @@ -45,7 +45,9 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 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); + return gl::OutOfMemory() + << "Failed to query the source surface description for mipmap generation, " + << gl::FmtHR(result); } D3DSURFACE_DESC sourceDesc; @@ -53,7 +55,9 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 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); + return gl::OutOfMemory() + << "Failed to query the destination surface description for mipmap generation, " + << gl::FmtHR(result); } ASSERT(sourceDesc.Format == destDesc.Format); @@ -61,23 +65,25 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); - ASSERT(d3dFormatInfo.mipGenerationFunction != NULL); + ASSERT(d3dFormatInfo.info().mipGenerationFunction != nullptr); D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + result = sourceSurface->LockRect(&sourceLocked, nullptr, 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); + return gl::OutOfMemory() << "Failed to lock the source surface for mipmap generation, " + << gl::FmtHR(result); } D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); + result = destSurface->LockRect(&destLocked, nullptr, 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); + return gl::OutOfMemory() << "Failed to lock the destination surface for mipmap generation, " + << gl::FmtHR(result); } const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits); @@ -85,40 +91,29 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 ASSERT(sourceData && destData); - d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, - destData, destLocked.Pitch, 0); + 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); + return gl::NoError(); } gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) { - IDirect3DSurface9 *sourceSurface = NULL; - gl::Error error = source->getSurface(&sourceSurface); - if (error.isError()) - { - return error; - } + IDirect3DSurface9 *sourceSurface = nullptr; + ANGLE_TRY(source->getSurface(&sourceSurface)); - IDirect3DSurface9 *destSurface = NULL; - error = dest->getSurface(&destSurface); - if (error.isError()) - { - return error; - } + IDirect3DSurface9 *destSurface = nullptr; + ANGLE_TRY(dest->getSurface(&destSurface)); - error = generateMip(destSurface, sourceSurface); - if (error.isError()) - { - return error; - } + ANGLE_TRY(generateMip(destSurface, sourceSurface)); dest->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) @@ -128,17 +123,17 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface HRESULT result; - result = source->LockRect(&sourceLock, NULL, 0); + result = source->LockRect(&sourceLock, nullptr, 0); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to lock source surface for copy, " << gl::FmtHR(result); } - result = dest->LockRect(&destLock, NULL, 0); + result = dest->LockRect(&destLock, nullptr, 0); if (FAILED(result)) { source->UnlockRect(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to lock source surface for copy, " << gl::FmtHR(result); } ASSERT(sourceLock.pBits && destLock.pBits); @@ -161,7 +156,85 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface source->UnlockRect(); dest->UnlockRect(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +// static +gl::Error Image9::CopyImage(const gl::Context *context, + Image9 *dest, + Image9 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + IDirect3DSurface9 *sourceSurface = nullptr; + ANGLE_TRY(source->getSurface(&sourceSurface)); + + IDirect3DSurface9 *destSurface = nullptr; + ANGLE_TRY(dest->getSurface(&destSurface)); + + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::OutOfMemory() + << "Failed to query the source surface description for mipmap generation, " + << gl::FmtHR(result); + } + const d3d9::D3DFormat &destD3DFormatInfo = d3d9::GetD3DFormatInfo(destDesc.Format); + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::OutOfMemory() + << "Failed to query the destination surface description for mipmap generation, " + << gl::FmtHR(result); + } + const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::OutOfMemory() << "Failed to lock the source surface for CopyImage, " + << gl::FmtHR(result); + } + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, nullptr, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + sourceSurface->UnlockRect(); + return gl::OutOfMemory() << "Failed to lock the destination surface for CopyImage, " + << gl::FmtHR(result); + } + + const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(sourceLocked.pBits) + + sourceRect.x * sourceD3DFormatInfo.pixelBytes + + sourceRect.y * sourceLocked.Pitch; + uint8_t *destData = reinterpret_cast<uint8_t *>(destLocked.pBits) + + destOffset.x * destD3DFormatInfo.pixelBytes + + destOffset.y * destLocked.Pitch; + ASSERT(sourceData && destData); + + CopyImageCHROMIUM(sourceData, sourceLocked.Pitch, sourceD3DFormatInfo.pixelBytes, + sourceD3DFormatInfo.info().colorReadFunction, destData, destLocked.Pitch, + destD3DFormatInfo.pixelBytes, destD3DFormatInfo.info().colorWriteFunction, + gl::GetUnsizedFormat(dest->getInternalFormat()), + destD3DFormatInfo.info().componentType, sourceRect.width, sourceRect.height, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); + + return gl::NoError(); } bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) @@ -189,7 +262,7 @@ bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &s mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); SafeRelease(mSurface); - mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); + mDirty = (d3d9FormatInfo.dataInitializerFunction != nullptr); return true; } @@ -201,11 +274,11 @@ gl::Error Image9::createSurface() { if (mSurface) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; + IDirect3DTexture9 *newTexture = nullptr; + IDirect3DSurface9 *newSurface = nullptr; const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; const D3DFORMAT d3dFormat = getD3DFormat(); @@ -218,20 +291,20 @@ gl::Error Image9::createSurface() IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, - poolToUse, &newTexture, NULL); + HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, + d3dFormat, poolToUse, &newTexture, nullptr); 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); + return gl::OutOfMemory() << "Failed to create image surface, " << gl::FmtHR(result); } newTexture->GetSurfaceLevel(levelToFetch, &newSurface); SafeRelease(newTexture); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - if (d3dFormatInfo.dataInitializerFunction != NULL) + if (d3dFormatInfo.dataInitializerFunction != nullptr) { RECT entireRect; entireRect.left = 0; @@ -244,7 +317,7 @@ gl::Error Image9::createSurface() ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to lock image surface, " << gl::FmtHR(result); } d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits), @@ -254,7 +327,7 @@ gl::Error Image9::createSurface() ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to unlock image surface, " << gl::FmtHR(result); } } } @@ -263,7 +336,7 @@ gl::Error Image9::createSurface() mDirty = false; mD3DPool = poolToUse; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) @@ -280,13 +353,13 @@ gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to lock image surface, " << gl::FmtHR(result); } mDirty = true; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image9::unlock() @@ -294,7 +367,6 @@ void Image9::unlock() if (mSurface) { HRESULT result = mSurface->UnlockRect(); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } } @@ -312,7 +384,9 @@ 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; + return (mSurface || + d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != nullptr) && + mDirty; } gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) @@ -324,14 +398,16 @@ gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) } *outSurface = mSurface; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) +gl::Error Image9::setManagedSurface2D(const gl::Context *context, + TextureStorage *storage, + int level) { - IDirect3DSurface9 *surface = NULL; + IDirect3DSurface9 *surface = nullptr; TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); - gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface); + gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, false, &surface); if (error.isError()) { return error; @@ -339,12 +415,15 @@ gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) return setManagedSurface(surface); } -gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) +gl::Error Image9::setManagedSurfaceCube(const gl::Context *context, + TextureStorage *storage, + int face, + int level) { - IDirect3DSurface9 *surface = NULL; + IDirect3DSurface9 *surface = nullptr; TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); - gl::Error error = - storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); + gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, + level, false, &surface); if (error.isError()) { return error; @@ -374,10 +453,13 @@ gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface) mD3DPool = desc.Pool; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error Image9::copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) { gl::Error error = createSurface(); if (error.isError()) @@ -387,11 +469,12 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); - IDirect3DSurface9 *destSurface = NULL; + IDirect3DSurface9 *destSurface = nullptr; if (index.type == GL_TEXTURE_2D) { - error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface); + error = + storage9->getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, true, &destSurface); if (error.isError()) { return error; @@ -400,7 +483,7 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i else { ASSERT(gl::IsCubeMapTextureTarget(index.type)); - error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface); + error = storage9->getSurfaceLevel(context, index.type, index.mipIndex, true, &destSurface); if (error.isError()) { return error; @@ -417,7 +500,7 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a ASSERT(area.width > 0 && area.height > 0 && area.depth == 1); ASSERT(destSurface); - IDirect3DSurface9 *sourceSurface = NULL; + IDirect3DSurface9 *sourceSurface = nullptr; gl::Error error = getSurface(&sourceSurface); if (error.isError()) { @@ -442,19 +525,22 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a sourceSurface->GetDesc(&desc); IDirect3DSurface9 *surf = 0; - HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &surf, nullptr); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result); + return gl::OutOfMemory() + << "Internal CreateOffscreenPlainSurface call failed, " << gl::FmtHR(result); } - copyLockableSurfaces(surf, sourceSurface); + auto err = copyLockableSurfaces(surf, sourceSurface); result = device->UpdateSurface(surf, &rect, destSurface, &point); SafeRelease(surf); + ANGLE_TRY(err); ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + return gl::OutOfMemory() << "Internal UpdateSurface call failed, " << gl::FmtHR(result); } } else @@ -464,27 +550,36 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + return gl::OutOfMemory() << "Internal UpdateSurface call failed, " << gl::FmtHR(result); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // 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 type, const void *input) +gl::Error Image9::loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) { // 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 = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); - GLsizei inputSkipBytes = formatInfo.computeSkipPixels(inputRowPitch, 0, unpack.skipImages, - unpack.skipRows, unpack.skipPixels); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLuint inputRowPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeRowPitch(type, 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); + ASSERT(d3dFormatInfo.loadFunction != nullptr); RECT lockRect = { @@ -500,31 +595,34 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa } d3dFormatInfo.loadFunction(area.width, area.height, area.depth, - reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, - inputRowPitch, 0, reinterpret_cast<uint8_t *>(locked.pBits), - locked.Pitch, 0); + reinterpret_cast<const uint8_t *>(input), inputRowPitch, 0, + reinterpret_cast<uint8_t *>(locked.pBits), locked.Pitch, 0); unlock(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) +gl::Error Image9::loadCompressedData(const gl::Context *context, + 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 = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); - GLsizei inputDepthPitch = - formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, 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); + ASSERT(d3d9FormatInfo.loadFunction != nullptr); RECT lockRect = { @@ -545,7 +643,7 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) unlock(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures @@ -565,16 +663,19 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, IDirect3DDevice9 *device = mRenderer->getDevice(); - IDirect3DSurface9 *renderTargetData = NULL; + IDirect3DSurface9 *renderTargetData = nullptr; D3DSURFACE_DESC description; surface->GetDesc(&description); - HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, + description.Format, D3DPOOL_SYSTEMMEM, + &renderTargetData, nullptr); if (FAILED(result)) { SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result); + return gl::OutOfMemory() << "Could not create matching destination surface, " + << gl::FmtHR(result); } result = device->GetRenderTargetData(surface, renderTargetData); @@ -583,7 +684,8 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, { SafeRelease(renderTargetData); SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result); + return gl::OutOfMemory() << "GetRenderTargetData unexpectedly failed, " + << gl::FmtHR(result); } int width = sourceArea.width; @@ -599,7 +701,9 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, { 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); + return gl::OutOfMemory() + << "Failed to lock the source surface (rectangle might be invalid), " + << gl::FmtHR(result); } D3DLOCKED_RECT destLock = {0}; @@ -776,13 +880,15 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, SafeRelease(surface); mDirty = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) +gl::Error Image9::copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) { RenderTargetD3D *renderTarget = nullptr; - gl::Error error = source->getRenderTarget(imageIndex, &renderTarget); + gl::Error error = source->getRenderTarget(context, imageIndex, &renderTarget); if (error.isError()) { return error; @@ -792,15 +898,16 @@ gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureSt return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget); } -gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset, +gl::Error Image9::copyFromFramebuffer(const gl::Context *context, + 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); + RenderTargetD3D *renderTarget = nullptr; + gl::Error error = srcAttachment->getRenderTarget(context, &renderTarget); if (error.isError()) { return error; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h index 91448cc849..01c60dc4fb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h @@ -26,27 +26,53 @@ class Image9 : public ImageD3D { public: Image9(Renderer9 *renderer); - ~Image9(); + ~Image9() override; static gl::Error generateMipmap(Image9 *dest, Image9 *source); static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + static gl::Error CopyImage(const gl::Context *context, + Image9 *dest, + Image9 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha); 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); - - virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); - virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - - gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; - gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + bool isDirty() const override; + + gl::Error setManagedSurface2D(const gl::Context *context, + TextureStorage *storage, + int level) override; + gl::Error setManagedSurfaceCube(const gl::Context *context, + TextureStorage *storage, + int face, + int level) override; + gl::Error copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) override; + + gl::Error loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) override; + gl::Error loadCompressedData(const gl::Context *context, + const gl::Box &area, + const void *input) override; + + gl::Error copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp index 97c7f72136..df86331766 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -14,7 +14,7 @@ namespace rx IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) { - mIndexBuffer = NULL; + mIndexBuffer = nullptr; mBufferSize = 0; mIndexType = 0; mDynamic = false; @@ -40,7 +40,7 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo } else if (indexType == GL_UNSIGNED_INT) { - ASSERT(mRenderer->getRendererExtensions().elementIndexUint); + ASSERT(mRenderer->getNativeExtensions().elementIndexUint); format = D3DFMT_INDEX32; } else UNREACHABLE(); @@ -54,7 +54,8 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo 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); + return gl::OutOfMemory() + << "Failed to allocate internal index buffer of size " << bufferSize; } } @@ -62,43 +63,43 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo mIndexType = indexType; mDynamic = dynamic; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; - void *mapPtr = NULL; + void *mapPtr = nullptr; 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); + return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(result); } *outMappedMemory = mapPtr; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBuffer9::unmapBuffer() { if (!mIndexBuffer) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "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::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } GLenum IndexBuffer9::getIndexType() const @@ -119,7 +120,7 @@ gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } @@ -127,7 +128,7 @@ gl::Error IndexBuffer9::discard() { if (!mIndexBuffer) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } void *dummy; @@ -136,16 +137,16 @@ gl::Error IndexBuffer9::discard() 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); + return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(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::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } D3DFORMAT IndexBuffer9::getIndexFormat() const diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h index ba03ba703f..5921d2a859 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h @@ -19,18 +19,18 @@ class IndexBuffer9 : public IndexBuffer { public: explicit IndexBuffer9(Renderer9 *const renderer); - virtual ~IndexBuffer9(); + ~IndexBuffer9() override; - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) override; - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual gl::Error unmapBuffer(); + gl::Error mapBuffer(unsigned int offset, unsigned int size, void **outMappedMemory) override; + gl::Error unmapBuffer() override; - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + GLenum getIndexType() const override; + unsigned int getBufferSize() const override; + gl::Error setSize(unsigned int bufferSize, GLenum indexType) override; - virtual gl::Error discard(); + gl::Error discard() override; D3DFORMAT getIndexFormat() const; IDirect3DIndexBuffer9 *getBuffer() const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp new file mode 100644 index 0000000000..388b8aa168 --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h new file mode 100644 index 0000000000..a56b08dc81 --- /dev/null +++ b/src/3rdparty/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/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp index c826abf81c..4ba053e6bd 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -19,7 +19,7 @@ Query9::Query9(Renderer9 *renderer, GLenum type) mResult(GL_FALSE), mQueryFinished(false), mRenderer(renderer), - mQuery(NULL) + mQuery(nullptr) { } @@ -30,23 +30,27 @@ Query9::~Query9() gl::Error Query9::begin() { - if (mQuery == NULL) + D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType()); + if (mQuery == nullptr) { - HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery); + 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); + return gl::OutOfMemory() << "Internal query creation failed, " << gl::FmtHR(result); } } - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) + if (d3dQueryType != D3DQUERYTYPE_EVENT) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.", result); + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::OutOfMemory() << "Failed to begin internal query, " << gl::FmtHR(result); + } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query9::end() @@ -57,19 +61,19 @@ gl::Error Query9::end() ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to end internal query, " << gl::FmtHR(result); } mQueryFinished = false; mResult = GL_FALSE; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query9::queryCounter() { UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "Unimplemented"); + return gl::InternalError() << "Unimplemented"; } template <typename T> @@ -91,7 +95,7 @@ gl::Error Query9::getResultBase(T *params) ASSERT(mQueryFinished); *params = static_cast<T>(mResult); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query9::getResult(GLint *params) @@ -124,7 +128,7 @@ gl::Error Query9::isResultAvailable(bool *available) *available = mQueryFinished; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query9::testQuery() @@ -133,38 +137,52 @@ gl::Error Query9::testQuery() { ASSERT(mQuery); - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) + HRESULT result = S_OK; + switch (getType()) { - mQueryFinished = true; + 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; + } - switch (getType()) + case GL_COMMANDS_COMPLETED_CHROMIUM: { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + 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: + default: UNREACHABLE(); break; - } } - else if (d3d9::isDeviceLostError(hres)) + + if (d3d9::isDeviceLostError(result)) { mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + return gl::OutOfMemory() << "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::OutOfMemory() << "Failed to test get query result, device is lost."; } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h index 9d17711a00..6c7c22f096 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h @@ -19,16 +19,16 @@ 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); + ~Query9() 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; private: gl::Error testQuery(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp index 419bff1f63..3e54c27f43 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp @@ -130,7 +130,8 @@ GLsizei SurfaceRenderTarget9::getDepth() const GLenum SurfaceRenderTarget9::getInternalFormat() const { - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); + return (mDepth ? mSwapChain->getDepthBufferInternalFormat() + : mSwapChain->getRenderTargetInternalFormat()); } GLsizei SurfaceRenderTarget9::getSamples() const diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h index f19c54de7b..bb3b5a4ee4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h @@ -21,7 +21,7 @@ class RenderTarget9 : public RenderTargetD3D { public: RenderTarget9() { } - virtual ~RenderTarget9() { } + ~RenderTarget9() override {} // Retrieve the texture that backs this render target, may be null for swap chain render // targets. virtual IDirect3DBaseTexture9 *getTexture() const = 0; @@ -43,7 +43,7 @@ class TextureRenderTarget9 : public RenderTarget9 GLsizei height, GLsizei depth, GLsizei samples); - virtual ~TextureRenderTarget9(); + ~TextureRenderTarget9() override; GLsizei getWidth() const override; GLsizei getHeight() const override; @@ -74,7 +74,7 @@ class SurfaceRenderTarget9 : public RenderTarget9 { public: SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth); - virtual ~SurfaceRenderTarget9(); + ~SurfaceRenderTarget9() override; GLsizei getWidth() const override; GLsizei getHeight() const override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index 6bb975b0e4..75c6298868 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -8,51 +8,51 @@ #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" -#include <sstream> #include <EGL/eglext.h> +#include <sstream> #include "common/utilities.h" -#include "libANGLE/angletypes.h" #include "libANGLE/Buffer.h" +#include "libANGLE/Context.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/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.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/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/renderer/d3d/TransformFeedbackD3D.h" -#include "libANGLE/State.h" -#include "libANGLE/Surface.h" -#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" #include "third_party/trace_event/trace_event.h" - - #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif @@ -69,69 +69,69 @@ 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_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; + mD3d9Module = nullptr; - mD3d9 = NULL; - mD3d9Ex = NULL; - mDevice = NULL; - mDeviceEx = NULL; - mDeviceWindow = NULL; - mBlit = NULL; + mD3d9 = nullptr; + mD3d9Ex = nullptr; + mDevice = nullptr; + mDeviceEx = nullptr; + mDeviceWindow = nullptr; + mBlit = nullptr; mAdapter = D3DADAPTER_DEFAULT; const egl::AttributeMap &attributes = display->getAttributeMap(); - EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + 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_HARDWARE_ANGLE: + mDeviceType = D3DDEVTYPE_HAL; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: - mDeviceType = D3DDEVTYPE_REF; - 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; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDeviceType = D3DDEVTYPE_NULLREF; + break; - default: - UNREACHABLE(); + default: + UNREACHABLE(); } - mMaskedClearSavedState = NULL; + mMaskedClearSavedState = nullptr; - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mLineLoopIB = NULL; - mCountingIB = NULL; + mVertexDataManager = nullptr; + mIndexDataManager = nullptr; + mLineLoopIB = nullptr; + mCountingIB = nullptr; 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; + mNullColorbufferCache[i].width = 0; + mNullColorbufferCache[i].height = 0; + mNullColorbufferCache[i].buffer = nullptr; } - mAppliedVertexShader = NULL; - mAppliedPixelShader = NULL; + mAppliedVertexShader = nullptr; + mAppliedPixelShader = nullptr; mAppliedProgramSerial = 0; - initializeDebugAnnotator(); + gl::InitializeDebugAnnotations(&mAnnotator); mEGLDevice = nullptr; } @@ -154,6 +154,10 @@ void Renderer9::release() { RendererD3D::cleanup(); + gl::UninitializeDebugAnnotations(); + + mTranslatedAttribCache.clear(); + releaseDeviceResources(); SafeDelete(mEGLDevice); @@ -167,10 +171,10 @@ void Renderer9::release() if (mDeviceWindow) { DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; + mDeviceWindow = nullptr; } - mD3d9Module = NULL; + mD3d9Module = nullptr; } egl::Error Renderer9::initialize() @@ -178,22 +182,25 @@ egl::Error Renderer9::initialize() TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9"); mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - if (mD3d9Module == NULL) + if (mD3d9Module == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found."); + return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "No D3D9 module found."; } - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + 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))) + // 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(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9)); + mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9)); ASSERT(mD3d9); } else @@ -204,12 +211,13 @@ egl::Error Renderer9::initialize() if (!mD3d9) { - return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device."); + return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "Could not create D3D9 device."; } if (mDisplay->getNativeDisplayId() != nullptr) { - // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context + // corresponds to } HRESULT result; @@ -226,13 +234,14 @@ egl::Error Renderer9::initialize() } else if (result == D3DERR_NOTAVAILABLE) { - Sleep(100); // Give the driver some time to initialize/recover + 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 + 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); + return egl::EglNotInitialized(D3D9_INIT_OTHER_ERROR) + << "Failed to get device caps, " << gl::FmtHR(result); } } } @@ -245,18 +254,17 @@ egl::Error Renderer9::initialize() 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); + return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_VERSION) + << "Renderer does not support PS " << minShaderModel << ".0, aborting!"; } - // 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. + // 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."); + return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_STRETCHRECT) + << "Renderer does not support StretctRect from textures."; } { @@ -265,43 +273,52 @@ egl::Error Renderer9::initialize() } static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); + 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); + mDeviceWindow = + CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, + 1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr); } D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED; + 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); + 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"); + return egl::EglBadAlloc(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); + 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"); + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || + result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return egl::EglBadAlloc(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(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); + result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx); ASSERT(SUCCEEDED(result)); } @@ -318,18 +335,19 @@ egl::Error Renderer9::initialize() // 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)); + SUCCEEDED(mD3d9->CheckDeviceFormat( + mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); - initializeDevice(); + ANGLE_TRY(initializeDevice()); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } // 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() +egl::Error Renderer9::initializeDevice() { // Permanent non-default states mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); @@ -337,14 +355,14 @@ void Renderer9::initializeDevice() if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize); } else { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f } - const gl::Caps &rendererCaps = getRendererCaps(); + const gl::Caps &rendererCaps = getNativeCaps(); mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); @@ -358,50 +376,55 @@ void Renderer9::initializeDevice() ASSERT(!mBlit); mBlit = new Blit9(this); - mBlit->initialize(); + ANGLE_TRY(mBlit->initialize()); ASSERT(!mVertexDataManager && !mIndexDataManager); mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this, getRendererClass()); + mIndexDataManager = new IndexDataManager(this); + + if (mVertexDataManager->initialize().isError()) + { + return egl::EglBadAlloc() << "Error initializing VertexDataManager"; + } + + mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes); + + mStateManager.initialize(); - // TODO(jmadill): use context caps, and place in common D3D location - mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes); + return egl::NoError(); } 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. + // 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.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; + 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() const +egl::ConfigSet Renderer9::generateConfigs() { - static const GLenum colorBufferFormats[] = - { - GL_BGR5_A1_ANGLEX, - GL_BGRA8_EXT, - GL_RGB565, + static const GLenum colorBufferFormats[] = { + GL_BGR5_A1_ANGLEX, GL_BGRA8_EXT, GL_RGB565, }; - static const GLenum depthStencilBufferFormats[] = - { + static const GLenum depthStencilBufferFormats[] = { GL_NONE, GL_DEPTH_COMPONENT32_OES, GL_DEPTH24_STENCIL8_OES, @@ -409,8 +432,8 @@ egl::ConfigSet Renderer9::generateConfigs() const GL_DEPTH_COMPONENT16, }; - const gl::Caps &rendererCaps = getRendererCaps(); - const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + const gl::Caps &rendererCaps = getNativeCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); D3DDISPLAYMODE currentDisplayMode; mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); @@ -449,56 +472,72 @@ egl::ConfigSet Renderer9::generateConfigs() const for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) { GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; - const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + const gl::TextureCaps &colorBufferFormatCaps = + rendererTextureCaps.get(colorBufferInternalFormat); if (colorBufferFormatCaps.renderable) { - for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) + 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) + 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); + const gl::InternalFormat &colorBufferFormatInfo = + gl::GetSizedInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = + gl::GetSizedInternalFormatInfo(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.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.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.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.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.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; + config.transparentBlueValue = 0; + config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType( + colorBufferFormatInfo.componentType); configs.add(config); } @@ -519,13 +558,12 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) outExtensions->d3dShareHandleClientBuffer = true; outExtensions->surfaceD3DTexture2DShareHandle = true; } + outExtensions->d3dTextureClientBuffer = true; outExtensions->querySurfacePointer = true; outExtensions->windowFixedSize = true; outExtensions->postSubBuffer = true; - outExtensions->createContext = true; outExtensions->deviceQuery = true; - outExtensions->createContextNoError = true; outExtensions->image = true; outExtensions->imageBase = true; @@ -533,6 +571,14 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) outExtensions->glRenderbufferImage = true; outExtensions->flexibleSurfaceCompatibility = true; + + // Contexts are virtualized so textures can be shared globally + outExtensions->displayTextureShareGroup = true; + + // D3D9 can be used without an output surface + outExtensions->surfacelessContext = true; + + outExtensions->robustResourceInitialization = true; } void Renderer9::startScene() @@ -540,7 +586,8 @@ void Renderer9::startScene() if (!mSceneStarted) { long result = mDevice->BeginScene(); - if (SUCCEEDED(result)) { + if (SUCCEEDED(result)) + { // This is defensive checking against the device being // lost at unexpected times. mSceneStarted = true; @@ -561,8 +608,8 @@ void Renderer9::endScene() gl::Error Renderer9::flush() { - IDirect3DQuery9* query = NULL; - gl::Error error = allocateEventQuery(&query); + IDirect3DQuery9 *query = nullptr; + gl::Error error = allocateEventQuery(&query); if (error.isError()) { return error; @@ -572,11 +619,11 @@ gl::Error Renderer9::flush() 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); + return gl::OutOfMemory() << "Failed to issue event query, " << gl::FmtHR(result); } // Grab the query data once - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); freeEventQuery(query); if (FAILED(result)) { @@ -585,16 +632,16 @@ gl::Error Renderer9::flush() notifyDeviceLost(); } - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer9::finish() { - IDirect3DQuery9* query = NULL; - gl::Error error = allocateEventQuery(&query); + IDirect3DQuery9 *query = nullptr; + gl::Error error = allocateEventQuery(&query); if (error.isError()) { return error; @@ -604,11 +651,11 @@ gl::Error Renderer9::finish() 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); + return gl::OutOfMemory() << "Failed to issue event query, " << gl::FmtHR(result); } // Grab the query data once - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); if (FAILED(result)) { if (d3d9::isDeviceLostError(result)) @@ -617,7 +664,7 @@ gl::Error Renderer9::finish() } freeEventQuery(query); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result); } // Loop until the query completes @@ -626,7 +673,7 @@ gl::Error Renderer9::finish() // Keep polling, but allow other threads to do something useful first ScheduleYield(); - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); // explicitly check for device loss // some drivers seem to return S_FALSE even if the device is lost @@ -644,34 +691,146 @@ gl::Error Renderer9::finish() } freeEventQuery(query); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result); } - } freeEventQuery(query); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +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(NativeWindow nativeWindow, +SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, - EGLint orientation) + EGLint orientation, + EGLint samples) { - return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, - orientation); + return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture, + backBufferFormat, depthBufferFormat, orientation); } -CompilerImpl *Renderer9::createCompiler() +egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config, + IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const { - return new CompilerD3D(SH_HLSL_3_0_OUTPUT); + IDirect3DTexture9 *texture = nullptr; + if (FAILED(d3dTexture->QueryInterface(&texture))) + { + return egl::EglBadParameter() << "Client buffer is not a IDirect3DTexture9"; + } + + IDirect3DDevice9 *textureDevice = nullptr; + texture->GetDevice(&textureDevice); + if (textureDevice != mDevice) + { + SafeRelease(texture); + return egl::EglBadParameter() << "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::EglBadParameter() + << "Unknown client buffer texture format: " << 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::NoError(); +} + +egl::Error Renderer9::validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const +{ + if (shareHandle == nullptr) + { + return egl::EglBadParameter() << "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::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(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::EglBadParameter() << "Invalid texture parameters in share handle texture."; + } + + return egl::NoError(); +} + +ContextImpl *Renderer9::createContext(const gl::ContextState &state) +{ + return new Context9(state, this); } void *Renderer9::getD3DDevice() { - return reinterpret_cast<void*>(mDevice); + return reinterpret_cast<void *>(mDevice); } gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) @@ -682,7 +841,7 @@ gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **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); + return gl::OutOfMemory() << "Failed to allocate event query, " << gl::FmtHR(result); } } else @@ -691,10 +850,10 @@ gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) mEventQueryPool.pop_back(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Renderer9::freeEventQuery(IDirect3DQuery9* query) +void Renderer9::freeEventQuery(IDirect3DQuery9 *query) { if (mEventQueryPool.size() > 1000) { @@ -706,20 +865,26 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query) } } -gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader) +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) +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) +HRESULT Renderer9::createVertexBuffer(UINT Length, + DWORD Usage, + IDirect3DVertexBuffer9 **ppVertexBuffer) { D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr); } VertexBuffer *Renderer9::createVertexBuffer() @@ -727,10 +892,13 @@ VertexBuffer *Renderer9::createVertexBuffer() return new VertexBuffer9(this); } -HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) +HRESULT Renderer9::createIndexBuffer(UINT Length, + DWORD Usage, + D3DFORMAT Format, + IDirect3DIndexBuffer9 **ppIndexBuffer) { D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr); } IndexBuffer *Renderer9::createIndexBuffer() @@ -738,36 +906,13 @@ IndexBuffer *Renderer9::createIndexBuffer() return new IndexBuffer9(this); } -BufferImpl *Renderer9::createBuffer() -{ - return new Buffer9(this); -} - -VertexArrayImpl *Renderer9::createVertexArray(const gl::VertexArray::Data &data) -{ - return new VertexArray9(data); -} - -QueryImpl *Renderer9::createQuery(GLenum type) -{ - return new Query9(this, type); -} - -FenceNVImpl *Renderer9::createFenceNV() -{ - return new FenceNV9(this); -} - -FenceSyncImpl *Renderer9::createFenceSync() +StreamProducerImpl *Renderer9::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) { - // Renderer9 doesn't support ES 3.0 and its sync objects. + // Streams are not supported under D3D9 UNREACHABLE(); - return NULL; -} - -TransformFeedbackImpl* Renderer9::createTransformFeedback() -{ - return new TransformFeedbackD3D(); + return nullptr; } bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const @@ -776,22 +921,24 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const return false; } -gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error Renderer9::fastCopyBufferToTexture(const gl::Context *context, + 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::generateSwizzle(gl::Texture *texture) -{ - // Swizzled textures are not available in ES2 or D3D9 - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) +gl::Error Renderer9::setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &samplerState) { CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates[index] : mCurVertexSamplerStates[index]; @@ -800,11 +947,7 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); TextureStorage *storage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&storage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(textureD3D->getNativeTexture(context, &storage)); // Storage should exist, texture should be complete ASSERT(storage); @@ -815,12 +958,16 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0) { int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; + 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_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)); + mDevice->SetSamplerState( + d3dSampler, D3DSAMP_MAGFILTER, + gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; float lodBias; @@ -830,52 +977,50 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias)); - if (getRendererExtensions().textureFilterAnisotropic) + if (getNativeExtensions().textureFilterAnisotropic) { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); + DWORD maxAnisotropy = + std::min(mDeviceCaps.MaxAnisotropy, static_cast<DWORD>(samplerState.maxAnisotropy)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy); } } - appliedSampler.forceSet = false; + appliedSampler.forceSet = false; appliedSampler.samplerState = samplerState; - appliedSampler.baseLevel = baseLevel; + appliedSampler.baseLevel = baseLevel; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +gl::Error Renderer9::setTexture(const gl::Context *context, + 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; + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + IDirect3DBaseTexture9 *d3dTexture = nullptr; + bool forceSetTexture = false; - std::vector<uintptr_t> &appliedTextures = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures; + 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; - } + ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage)); // Texture should be complete and have a storage ASSERT(texStorage); TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage); - error = storage9->getBaseTexture(&d3dTexture); - if (error.isError()) - { - return error; - } + ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture)); // 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); + ASSERT(d3dTexture != nullptr); forceSetTexture = textureImpl->hasDirtyImages(); textureImpl->resetDirty(); @@ -888,60 +1033,50 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/, - const std::vector<GLint> &/*vertexUniformBuffers*/, - const std::vector<GLint> &/*fragmentUniformBuffers*/) +gl::Error Renderer9::updateState(const gl::Context *context, GLenum drawMode) { - // No effect in ES2/D3D9 - return gl::Error(GL_NO_ERROR); -} + const auto &glState = context->getGLState(); -void Renderer9::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) -{ - mStateManager.syncState(state, bitmask); -} - -gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode) -{ // Applies the render target surface, depth stencil surface, viewport rectangle and // scissor rectangle to the renderer - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete()); - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } + ANGLE_TRY(applyRenderTarget(context, framebuffer)); // Setting viewport state - setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), - data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace, - false); + setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode, + glState.getRasterizerState().frontFace, false); // Setting scissors state - setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); + setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); // Setting blend, depth stencil, and rasterizer states - int samples = framebufferObject->getSamples(data); - gl::RasterizerState rasterizer = data.state->getRasterizerState(); + // 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; + const gl::FramebufferAttachment *firstColorAttachment = framebuffer->getFirstColorbuffer(); + if (firstColorAttachment) + { + ASSERT(firstColorAttachment->isAttached()); + RenderTarget9 *renderTarget = nullptr; + ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget)); + samples = renderTarget->getSamples(); + } + gl::RasterizerState rasterizer = glState.getRasterizerState(); rasterizer.pointDrawMode = (drawMode == GL_POINTS); rasterizer.multiSample = (samples != 0); - unsigned int mask = GetBlendSampleMask(data, samples); - error = setBlendDepthRasterStates(data, mask); - - if (error.isError()) - { - return error; - } + unsigned int mask = GetBlendSampleMask(glState, samples); + ANGLE_TRY(setBlendDepthRasterStates(context, mask)); mStateManager.resetDirtyBits(); - return error; + return gl::NoError(); } void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) @@ -949,71 +1084,85 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) mStateManager.setScissorState(scissor, enabled); } -gl::Error Renderer9::setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode) +gl::Error Renderer9::setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode) { - int samples = glData.state->getDrawFramebuffer()->getSamples(glData); - gl::RasterizerState rasterizer = glData.state->getRasterizerState(); + const auto &glState = context->getGLState(); + gl::Framebuffer *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; + const gl::FramebufferAttachment *firstColorAttachment = drawFramebuffer->getFirstColorbuffer(); + if (firstColorAttachment) + { + ASSERT(firstColorAttachment->isAttached()); + RenderTarget9 *renderTarget = nullptr; + ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &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(*glData.state, mask); + unsigned int mask = GetBlendSampleMask(glState, samples); + return mStateManager.setBlendDepthRasterStates(glState, mask); } -void Renderer9::setViewport(const gl::Caps *caps, - const gl::Rectangle &viewport, +void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport) { - mStateManager.setViewportState(caps, viewport, zNear, zFar, drawMode, frontFace, - 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; + 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(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer) +gl::Error Renderer9::getNullColorbuffer(const gl::Context *context, + const gl::FramebufferAttachment *depthbuffer, + const gl::FramebufferAttachment **outColorBuffer) { ASSERT(depthbuffer); @@ -1022,25 +1171,28 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu // search cached nullcolorbuffers for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { - if (mNullColorbufferCache[i].buffer != NULL && + if (mNullColorbufferCache[i].buffer != nullptr && mNullColorbufferCache[i].width == size.width && mNullColorbufferCache[i].height == size.height) { mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; - *outColorBuffer = mNullColorbufferCache[i].buffer; - return gl::Error(GL_NO_ERROR); + *outColorBuffer = mNullColorbufferCache[i].buffer; + return gl::NoError(); } } - gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); - gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height); + auto *implFactory = context->getImplementation(); + + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0); + gl::Error error = nullRenderbuffer->setStorage(context, 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); + gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment( + context, GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer); // add nullbuffer to the cache NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; @@ -1053,46 +1205,38 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu } delete oldest->buffer; - oldest->buffer = nullbuffer; + oldest->buffer = nullbuffer; oldest->lruCount = ++mMaxNullColorbufferLRU; oldest->width = size.width; oldest->height = size.height; *outColorBuffer = nullbuffer; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAttachment, +gl::Error Renderer9::applyRenderTarget(const gl::Context *context, + 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(depthStencilAttachment, &renderAttachment); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getNullColorbuffer(context, depthStencilAttachment, &renderAttachment)); } ASSERT(renderAttachment != nullptr); - size_t renderTargetWidth = 0; - size_t renderTargetHeight = 0; + size_t renderTargetWidth = 0; + size_t renderTargetHeight = 0; D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN; RenderTarget9 *renderTarget = nullptr; - error = renderAttachment->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(renderAttachment->getRenderTarget(context, &renderTarget)); ASSERT(renderTarget); - bool renderTargetChanged = false; + bool renderTargetChanged = false; unsigned int renderTargetSerial = renderTarget->getSerial(); if (renderTargetSerial != mAppliedRenderTargetSerial) { @@ -1103,24 +1247,20 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt mDevice->SetRenderTarget(0, renderTargetSurface); SafeRelease(renderTargetSurface); - renderTargetWidth = renderTarget->getWidth(); + renderTargetWidth = renderTarget->getWidth(); renderTargetHeight = renderTarget->getHeight(); renderTargetFormat = renderTarget->getD3DFormat(); mAppliedRenderTargetSerial = renderTargetSerial; - renderTargetChanged = true; + renderTargetChanged = true; } RenderTarget9 *depthStencilRenderTarget = nullptr; - unsigned int depthStencilSerial = 0; + unsigned int depthStencilSerial = 0; if (depthStencilAttachment != nullptr) { - error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget)); ASSERT(depthStencilRenderTarget); depthStencilSerial = depthStencilRenderTarget->getSerial(); @@ -1128,7 +1268,7 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized) { - unsigned int depthSize = 0; + unsigned int depthSize = 0; unsigned int stencilSize = 0; // Apply the depth stencil on the device @@ -1140,19 +1280,19 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt mDevice->SetDepthStencilSurface(depthStencilSurface); SafeRelease(depthStencilSurface); - depthSize = depthStencilAttachment->getDepthSize(); + depthSize = depthStencilAttachment->getDepthSize(); stencilSize = depthStencilAttachment->getStencilSize(); } else { - mDevice->SetDepthStencilSurface(NULL); + mDevice->SetDepthStencilSurface(nullptr); } mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize); mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize); mAppliedDepthStencilSerial = depthStencilSerial; - mDepthStencilInitialized = true; + mDepthStencilInitialized = true; } if (renderTargetChanged || !mRenderTargetDescInitialized) @@ -1163,83 +1303,84 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt mRenderTargetDescInitialized = true; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) +gl::Error Renderer9::applyRenderTarget(const gl::Context *context, + const gl::Framebuffer *framebuffer) { - return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer()); + return applyRenderTarget(context, framebuffer->getColorbuffer(0), + framebuffer->getDepthOrStencilbuffer()); } -gl::Error Renderer9::applyVertexBuffer(const gl::State &state, +gl::Error Renderer9::applyVertexBuffer(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei instances, TranslatedIndexData * /*indexInfo*/) { - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); + const gl::State &state = context->getGLState(); + gl::Error error = mVertexDataManager->prepareVertexData(context, first, count, + &mTranslatedAttribCache, instances); if (error.isError()) { return error; } - return mVertexDeclarationCache.applyDeclaration(mDevice, mTranslatedAttribCache, state.getProgram(), instances, &mRepeatDraw); + 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::Data &data, - const GLvoid *indices, +gl::Error Renderer9::applyIndexBuffer(const gl::Context *context, + const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - gl::VertexArray *vao = data.state->getVertexArray(); + gl::VertexArray *vao = context->getGLState().getVertexArray(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, - indexInfo, false); - if (error.isError()) - { - return error; - } + const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>(); + + GLenum dstType = GetIndexTranslationDestType(type, lazyIndexRange, false); + + ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer, + indices, indexInfo)); // Directly binding the storage buffer is not supported for d3d9 - ASSERT(indexInfo->storage == NULL); + ASSERT(indexInfo->storage == nullptr); if (indexInfo->serial != mAppliedIBSerial) { - IndexBuffer9* indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer); + IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer); mDevice->SetIndices(indexBuffer->getBuffer()); mAppliedIBSerial = indexInfo->serial; } - return gl::Error(GL_NO_ERROR); -} - -void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) -{ - ASSERT(!state.isTransformFeedbackActiveUnpaused()); + return gl::NoError(); } -gl::Error Renderer9::drawArraysImpl(const gl::Data &data, +gl::Error Renderer9::drawArraysImpl(const gl::Context *context, GLenum mode, + GLint startVertex, GLsizei count, GLsizei instances) { - ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); + ASSERT(!context->getGLState().isTransformFeedbackActiveUnpaused()); startScene(); if (mode == GL_LINE_LOOP) { - return drawLineLoop(count, GL_NONE, NULL, 0, NULL); + return drawLineLoop(context, count, GL_NONE, nullptr, 0, nullptr); } else if (instances > 0) { - StaticIndexBufferInterface *countingIB = NULL; - gl::Error error = getCountingIB(count, &countingIB); + StaticIndexBufferInterface *countingIB = nullptr; + gl::Error error = getCountingIB(count, &countingIB); if (error.isError()) { return error; @@ -1258,60 +1399,73 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data, mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - else // Regular case + else // Regular case { mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } -gl::Error Renderer9::drawElementsImpl(const gl::Data &data, - const TranslatedIndexData &indexInfo, +gl::Error Renderer9::drawElementsImpl(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, - GLsizei /*instances*/) + const void *indices, + GLsizei instances) { + TranslatedIndexData indexInfo; + + ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo)); + + const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>(); + const gl::IndexRange &indexRange = lazyIndexRange.getIndexRange().value(); + size_t vertexCount = indexRange.vertexCount(); + ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start), + static_cast<GLsizei>(vertexCount), instances, &indexInfo)); + startScene(); - int minIndex = static_cast<int>(indexInfo.indexRange.start); + int minIndex = static_cast<int>(indexRange.start); - gl::VertexArray *vao = data.state->getVertexArray(); + gl::VertexArray *vao = context->getGLState().getVertexArray(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); if (mode == GL_POINTS) { - return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); + return drawIndexedPoints(context, count, type, indices, minIndex, elementArrayBuffer); } else if (mode == GL_LINE_LOOP) { - return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + return drawLineLoop(context, 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); + return gl::NoError(); } } -gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +gl::Error Renderer9::drawLineLoop(const gl::Context *context, + GLsizei count, + GLenum type, + const void *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); + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + const uint8_t *bufferData = nullptr; + gl::Error error = storage->getData(context, &bufferData); if (error.isError()) { return error; @@ -1321,12 +1475,13 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi unsigned int startIndex = 0; - if (getRendererExtensions().elementIndexUint) + if (getNativeExtensions().elementIndexUint) { if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + gl::Error error = + mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mLineLoopIB); @@ -1337,60 +1492,64 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi // Checked by Renderer9::applyPrimitiveType ASSERT(count >= 0); - if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) + 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."); + return gl::OutOfMemory() << "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); + 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; + void *mappedMemory = nullptr; unsigned int offset = 0; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + 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); + 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(); + 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(); @@ -1404,7 +1563,8 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + gl::Error error = + mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); if (error.isError()) { SafeDelete(mLineLoopIB); @@ -1415,19 +1575,22 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi // Checked by Renderer9::applyPrimitiveType ASSERT(count >= 0); - if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short))) + 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."); + return gl::OutOfMemory() << "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); + 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; + void *mappedMemory = nullptr; unsigned int offset; error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); if (error.isError()) @@ -1435,40 +1598,41 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi return error; } - startIndex = static_cast<unsigned int>(offset) / 2; - unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); + 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(); + 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(); @@ -1488,22 +1652,31 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } template <typename T> -static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +static gl::Error drawPoints(IDirect3DDevice9 *device, + GLsizei count, + const void *indices, + int minIndex) { for (int i = 0; i < count; i++) { - unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]) - minIndex; + 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); + return gl::NoError(); } -gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +gl::Error Renderer9::drawIndexedPoints(const gl::Context *context, + GLsizei count, + GLenum type, + const void *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. @@ -1511,10 +1684,10 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid if (elementArrayBuffer) { BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); - intptr_t offset = reinterpret_cast<intptr_t>(indices); + intptr_t offset = reinterpret_cast<intptr_t>(indices); - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); + const uint8_t *bufferData = nullptr; + gl::Error error = storage->getData(context, &bufferData); if (error.isError()) { return error; @@ -1525,17 +1698,22 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid 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); + 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::InternalError(); } } 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 + if (count <= 65536) // 16-bit indices { const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short); @@ -1543,29 +1721,21 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou { SafeDelete(mCountingIB); mCountingIB = new StaticIndexBufferInterface(this); - mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + ANGLE_TRY(mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)); - void *mappedMemory = NULL; - gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); - if (error.isError()) - { - return error; - } + void *mappedMemory = nullptr; + ANGLE_TRY(mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr)); - unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); + 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; - } + ANGLE_TRY(mCountingIB->unmapBuffer()); } } - else if (getRendererExtensions().elementIndexUint) + else if (getNativeExtensions().elementIndexUint) { const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int); @@ -1573,59 +1743,53 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou { SafeDelete(mCountingIB); mCountingIB = new StaticIndexBufferInterface(this); - mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + ANGLE_TRY(mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); - void *mappedMemory = NULL; - gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); - if (error.isError()) - { - return error; - } + void *mappedMemory = nullptr; + ANGLE_TRY(mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr)); - unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); + 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; - } + ANGLE_TRY(mCountingIB->unmapBuffer()); } } else { - return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced."); + return gl::OutOfMemory() + << "Could not create a counting index buffer for glDrawArraysInstanced."; } *outIB = mCountingIB; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/) +gl::Error Renderer9::applyShaders(const gl::Context *context, GLenum drawMode) { - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - const auto &inputLayout = programD3D->getCachedInputLayout(); + const gl::State &state = context->getContextState().getState(); + // This method is called single-threaded. + ANGLE_TRY(ensureHLSLCompilerInitialized()); - ShaderExecutableD3D *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); - if (error.isError()) - { - return error; - } + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(state.getProgram()); + VertexArray9 *vao = GetImplAs<VertexArray9>(state.getVertexArray()); + programD3D->updateCachedInputLayout(vao->getCurrentStateSerial(), state); - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); - if (error.isError()) - { - return error; - } + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr)); + + const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer(); + programD3D->updateCachedOutputLayout(context, drawFramebuffer); + + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); - IDirect3DVertexShader9 *vertexShader = (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr); - IDirect3DPixelShader9 *pixelShader = (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr); + IDirect3DVertexShader9 *vertexShader = + (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr); + IDirect3DPixelShader9 *pixelShader = + (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr); if (vertexShader != mAppliedVertexShader) { @@ -1652,25 +1816,39 @@ gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/) mAppliedProgramSerial = programSerial; } - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(applyUniforms(programD3D)); + + // Driver uniforms + mStateManager.setShaderConstants(); + + return gl::NoError(); } -gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, - GLenum /*drawMode*/, - const std::vector<D3DUniform *> &uniformArray) +gl::Error Renderer9::applyUniforms(ProgramD3D *programD3D) { + // Skip updates if we're not dirty. Note that D3D9 cannot have compute. + if (!programD3D->areVertexUniformsDirty() && !programD3D->areFragmentUniformsDirty()) + { + return gl::NoError(); + } + + const auto &uniformArray = programD3D->getD3DUniforms(); + for (const D3DUniform *targetUniform : uniformArray) { - if (!targetUniform->dirty) + // Built-in uniforms must be skipped. + if (!targetUniform->isReferencedByFragmentShader() && + !targetUniform->isReferencedByVertexShader()) continue; - GLfloat *f = (GLfloat *)targetUniform->data; - GLint *i = (GLint *)targetUniform->data; + const GLfloat *f = reinterpret_cast<const GLfloat *>(targetUniform->firstNonNullData()); + const GLint *i = reinterpret_cast<const GLint *>(targetUniform->firstNonNullData()); - switch (targetUniform->type) + switch (targetUniform->typeInfo.type) { case GL_SAMPLER_2D: case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: break; case GL_BOOL: case GL_BOOL_VEC2: @@ -1698,22 +1876,22 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, } } - // Driver uniforms - mStateManager.setShaderConstants(); - - return gl::Error(GL_NO_ERROR); + programD3D->markUniformsClean(); + return gl::NoError(); } void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v) { if (targetUniform->isReferencedByFragmentShader()) { - mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, + targetUniform->registerCount); } if (targetUniform->isReferencedByVertexShader()) { - mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, + targetUniform->registerCount); } } @@ -1730,7 +1908,7 @@ void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v) vector[i][3] = (GLfloat)v[4 * i + 3]; } - applyUniformnfv(targetUniform, (GLfloat*)vector); + applyUniformnfv(targetUniform, (GLfloat *)vector); } void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v) @@ -1746,18 +1924,19 @@ void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v) vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; } - applyUniformnfv(targetUniform, (GLfloat*)vector); + applyUniformnfv(targetUniform, (GLfloat *)vector); } -gl::Error Renderer9::clear(const ClearParameters &clearParams, +gl::Error Renderer9::clear(const gl::Context *context, + const ClearParameters &clearParams, const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer) { - if (clearParams.colorClearType != GL_FLOAT) + if (clearParams.colorType != GL_FLOAT) { // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } bool clearColor = clearParams.clearColor[0]; @@ -1765,14 +1944,15 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, { if (clearParams.clearColor[i] != clearColor) { - // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 + // Clearing individual buffers other than buffer zero is not supported by Renderer9 and + // ES 2.0 UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } } - float depth = gl::clamp01(clearParams.depthClearValue); - DWORD stencil = clearParams.stencilClearValue & 0x000000FF; + float depth = gl::clamp01(clearParams.depthValue); + DWORD stencil = clearParams.stencilValue & 0x000000FF; unsigned int stencilUnmasked = 0x0; if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0) @@ -1780,7 +1960,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, ASSERT(depthStencilBuffer != nullptr); RenderTargetD3D *stencilRenderTarget = nullptr; - gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget); + gl::Error error = depthStencilBuffer->getRenderTarget(context, &stencilRenderTarget); if (error.isError()) { return error; @@ -1789,21 +1969,23 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, RenderTarget9 *stencilRenderTarget9 = GetAs<RenderTarget9>(stencilRenderTarget); ASSERT(stencilRenderTarget9); - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); + const d3d9::D3DFormat &d3dFormatInfo = + d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1; } - const bool needMaskedStencilClear = clearParams.clearStencil && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + const bool needMaskedStencilClear = + clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; bool needMaskedColorClear = false; - D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); + D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); if (clearColor) { ASSERT(colorBuffer != nullptr); - RenderTargetD3D *colorRenderTarget = NULL; - gl::Error error = colorBuffer->getRenderTarget(&colorRenderTarget); + RenderTargetD3D *colorRenderTarget = nullptr; + gl::Error error = colorBuffer->getRenderTarget(context, &colorRenderTarget); if (error.isError()) { return error; @@ -1812,17 +1994,27 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, RenderTarget9 *colorRenderTarget9 = GetAs<RenderTarget9>(colorRenderTarget); ASSERT(colorRenderTarget9); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat()); - 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) || + 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.colorF.alpha), + gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) + ? 0.0f + : clearParams.colorF.red), + gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) + ? 0.0f + : clearParams.colorF.green), + gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) + ? 0.0f + : clearParams.colorF.blue)); + + if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || - (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { needMaskedColorClear = true; @@ -1835,7 +2027,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, // 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) + if (mMaskedClearSavedState == nullptr) { hr = mDevice->BeginStateBlock(); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); @@ -1850,10 +2042,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); + mDevice->SetPixelShader(nullptr); + mDevice->SetVertexShader(nullptr); mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - mDevice->SetStreamSource(0, NULL, 0, 0); + mDevice->SetStreamSource(0, nullptr, 0, 0); mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); @@ -1862,7 +2054,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { mDevice->SetStreamSourceFreq(i, 1); } @@ -1871,9 +2063,9 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); } - ASSERT(mMaskedClearSavedState != NULL); + ASSERT(mMaskedClearSavedState != nullptr); - if (mMaskedClearSavedState != NULL) + if (mMaskedClearSavedState != nullptr) { hr = mMaskedClearSavedState->Capture(); ASSERT(SUCCEEDED(hr)); @@ -1890,11 +2082,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, if (clearColor) { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, - gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, - clearParams.colorMaskGreen, - clearParams.colorMaskBlue, - clearParams.colorMaskAlpha)); + mDevice->SetRenderState( + D3DRS_COLORWRITEENABLE, + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen, + clearParams.colorMaskBlue, clearParams.colorMaskAlpha)); } else { @@ -1917,8 +2108,8 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); } - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); + mDevice->SetPixelShader(nullptr); + mDevice->SetVertexShader(nullptr); mDevice->SetFVF(D3DFVF_XYZRHW); mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); @@ -1928,7 +2119,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { mDevice->SetStreamSourceFreq(i, 1); } @@ -1936,7 +2127,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, int renderTargetWidth = mStateManager.getRenderTargetWidth(); int renderTargetHeight = mStateManager.getRenderTargetHeight(); - float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + 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; @@ -1964,10 +2155,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, { mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); + mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil); } - if (mMaskedClearSavedState != NULL) + if (mMaskedClearSavedState != nullptr) { mMaskedClearSavedState->Apply(); } @@ -1988,17 +2179,17 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, dxClearFlags |= D3DCLEAR_STENCIL; } - mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Renderer9::markAllStateDirty() { - mAppliedRenderTargetSerial = 0; - mAppliedDepthStencilSerial = 0; - mDepthStencilInitialized = false; + mAppliedRenderTargetSerial = 0; + mAppliedDepthStencilSerial = 0; + mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; mStateManager.forceSetRasterState(); @@ -2021,9 +2212,9 @@ void Renderer9::markAllStateDirty() mCurPixelTextures[i] = angle::DirtyPointer; } - mAppliedIBSerial = 0; - mAppliedVertexShader = NULL; - mAppliedPixelShader = NULL; + mAppliedIBSerial = 0; + mAppliedVertexShader = nullptr; + mAppliedPixelShader = nullptr; mAppliedProgramSerial = 0; mStateManager.forceSetDXUniformsState(); @@ -2051,6 +2242,10 @@ void Renderer9::releaseDeviceResources() for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { + if (mNullColorbufferCache[i].buffer) + { + mNullColorbufferCache[i].buffer->detach(mDisplay->getProxyContext()); + } SafeDelete(mNullColorbufferCache[i].buffer); } } @@ -2059,19 +2254,7 @@ void Renderer9::releaseDeviceResources() bool Renderer9::testDeviceLost() { HRESULT status = getDeviceStatusCode(); - bool isLost = FAILED(status); - - if (isLost) - { - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - } - - return isLost; + return FAILED(status); } HRESULT Renderer9::getDeviceStatusCode() @@ -2080,7 +2263,7 @@ HRESULT Renderer9::getDeviceStatusCode() if (mDeviceEx) { - status = mDeviceEx->CheckDeviceState(NULL); + status = mDeviceEx->CheckDeviceState(nullptr); } else if (mDevice) { @@ -2096,16 +2279,16 @@ bool Renderer9::testDeviceResettable() // 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; + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != nullptr); + case D3DERR_DEVICEREMOVED: + ASSERT(mDeviceEx != nullptr); + return isRemovedDeviceResettable(); + default: + return false; } } @@ -2115,12 +2298,12 @@ bool Renderer9::resetDevice() D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - HRESULT result = D3D_OK; - bool lost = testDeviceLost(); + 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); + ASSERT(mDeviceEx != nullptr || !removedDevice); for (int attempts = 3; lost && attempts > 0; attempts--) { @@ -2134,16 +2317,16 @@ bool Renderer9::resetDevice() } else if (mDeviceEx) { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - lost = testDeviceLost(); + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, nullptr); + lost = testDeviceLost(); } else { result = mDevice->TestCooperativeLevel(); while (result == D3DERR_DEVICELOST) { - Sleep(100); // Give the graphics driver some CPU time + Sleep(100); // Give the graphics driver some CPU time result = mDevice->TestCooperativeLevel(); } @@ -2157,13 +2340,13 @@ bool Renderer9::resetDevice() if (FAILED(result)) { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result); return false; } if (removedDevice && lost) { - ERR("Device lost reset failed multiple times"); + ERR() << "Device lost reset failed multiple times"; return false; } @@ -2171,11 +2354,12 @@ bool Renderer9::resetDevice() if (!removedDevice) { // reset device defaults - initializeDevice(); + if (initializeDevice().isError()) + { + return false; + } } - mDeviceLost = false; - return true; } @@ -2184,15 +2368,16 @@ 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")); + IDirect3D9Ex *d3d9Ex = nullptr; + 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); + success = SUCCEEDED(result); } SafeRelease(d3d9Ex); @@ -2232,20 +2417,22 @@ std::string Renderer9::getRendererDescription() const 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); + 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; + 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; } @@ -2260,20 +2447,10 @@ 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(); + return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive(); } int Renderer9::getMajorShaderModel() const @@ -2298,7 +2475,7 @@ DWORD Renderer9::getCapsDeclTypes() const D3DPOOL Renderer9::getBufferPool(DWORD usage) const { - if (mD3d9Ex != NULL) + if (mD3d9Ex != nullptr) { return D3DPOOL_DEFAULT; } @@ -2313,66 +2490,126 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const 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) +gl::Error Renderer9::copyImage2D(const gl::Context *context, + 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.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); + return mBlit->copy2D(context, 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) +gl::Error Renderer9::copyImageCube(const gl::Context *context, + 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.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); + return mBlit->copyCube(context, 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) +gl::Error Renderer9::copyImage3D(const gl::Context *context, + 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); + return gl::InternalError(); } -gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage2DArray(const gl::Context *context, + 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); + return gl::InternalError(); +} + +gl::Error Renderer9::copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage, + destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha); } -gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +gl::Error Renderer9::copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) +{ + UNIMPLEMENTED(); + return gl::InternalError(); +} + +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 = getRendererTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); + const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); IDirect3DTexture9 *texture = nullptr; - IDirect3DSurface9 *renderTarget = NULL; + IDirect3DSurface9 *renderTarget = nullptr; if (width > 0 && height > 0) { bool requiresInitialization = false; - HRESULT result = D3DERR_INVALIDCALL; + HRESULT result = D3DERR_INVALIDCALL; - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format); if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { - result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &renderTarget, NULL); + result = mDevice->CreateDepthStencilSurface( + width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr); } else { @@ -2398,25 +2635,25 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to create render target, " << gl::FmtHR(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; + // 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 = nullptr; mDevice->GetRenderTarget(0, &prevRenderTarget); mDevice->SetRenderTarget(0, renderTarget); - mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + mDevice->Clear(0, nullptr, 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); + return gl::NoError(); } gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) @@ -2424,7 +2661,7 @@ gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTarge ASSERT(source != nullptr); RenderTargetD3D *newRT = nullptr; - gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), + gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), source->getInternalFormat(), source->getSamples(), &newRT); if (error.isError()) { @@ -2439,31 +2676,16 @@ gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTarge 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); + return gl::OutOfMemory() << "Failed to copy render target, " << gl::FmtHR(result); } *outRT = newRT; - return gl::Error(GL_NO_ERROR); -} - -FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data) -{ - return new Framebuffer9(data, this); -} - -ShaderImpl *Renderer9::createShader(const gl::Shader::Data &data) -{ - return new ShaderD3D(data); + return gl::NoError(); } -ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data) -{ - return new ProgramD3D(data, this); -} - -gl::Error Renderer9::loadExecutable(const void *function, +gl::Error Renderer9::loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) @@ -2473,10 +2695,10 @@ gl::Error Renderer9::loadExecutable(const void *function, switch (type) { - case SHADER_VERTEX: + case gl::SHADER_VERTEX: { - IDirect3DVertexShader9 *vshader = NULL; - gl::Error error = createVertexShader((DWORD*)function, length, &vshader); + IDirect3DVertexShader9 *vshader = nullptr; + gl::Error error = createVertexShader((DWORD *)function, length, &vshader); if (error.isError()) { return error; @@ -2484,10 +2706,10 @@ gl::Error Renderer9::loadExecutable(const void *function, *outExecutable = new ShaderExecutable9(function, length, vshader); } break; - case SHADER_PIXEL: + case gl::SHADER_FRAGMENT: { - IDirect3DPixelShader9 *pshader = NULL; - gl::Error error = createPixelShader((DWORD*)function, length, &pshader); + IDirect3DPixelShader9 *pshader = nullptr; + gl::Error error = createPixelShader((DWORD *)function, length, &pshader); if (error.isError()) { return error; @@ -2495,41 +2717,45 @@ gl::Error Renderer9::loadExecutable(const void *function, *outExecutable = new ShaderExecutable9(function, length, pshader); } break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + default: + UNREACHABLE(); + return gl::InternalError(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) { // Transform feedback is not supported in ES2 or D3D9 ASSERT(streamOutVaryings.empty()); - const char *profileType = NULL; + std::stringstream profileStream; + switch (type) { - case SHADER_VERTEX: - profileType = "vs"; - break; - case SHADER_PIXEL: - profileType = "ps"; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + case gl::SHADER_VERTEX: + profileStream << "vs"; + break; + case gl::SHADER_FRAGMENT: + profileStream << "ps"; + break; + default: + UNREACHABLE(); + return gl::InternalError(); } - unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; - unsigned int profileMinorVersion = 0; - std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); + + profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2); + profileStream << "_" + << "0"; + + std::string profile = profileStream.str(); UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; @@ -2551,31 +2777,35 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, 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. + // 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, "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; + ID3DBlob *binary = nullptr; std::string debugInfo; - gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo); + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, nullptr, + &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. + // 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); + *outExectuable = nullptr; + return gl::NoError(); } - error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - streamOutVaryings, separatedOutputBuffers, outExectuable); + error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()), + binary->GetBufferSize(), type, streamOutVaryings, separatedOutputBuffers, + outExectuable); SafeRelease(binary); if (error.isError()) @@ -2588,7 +2818,12 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, (*outExectuable)->appendDebugInfo(debugInfo); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error Renderer9::ensureHLSLCompilerInitialized() +{ + return mCompiler.ensureInitialized(); } UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize) @@ -2603,7 +2838,7 @@ gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *des D3DPOOL Renderer9::getTexturePool(DWORD usage) const { - if (mD3d9Ex != NULL) + if (mD3d9Ex != nullptr) { return D3DPOOL_DEFAULT; } @@ -2618,7 +2853,9 @@ D3DPOOL Renderer9::getTexturePool(DWORD usage) const return D3DPOOL_DEFAULT; } -gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, + IDirect3DSurface9 *source, + bool fromManaged) { ASSERT(source && dest); @@ -2630,28 +2867,34 @@ gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurfac source->GetDesc(&desc); IDirect3DSurface9 *surf = 0; - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &surf, nullptr); if (SUCCEEDED(result)) { - Image9::copyLockableSurfaces(surf, source); - result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + ANGLE_TRY(Image9::copyLockableSurfaces(surf, source)); + result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr); SafeRelease(surf); } } else { endScene(); - result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + result = mDevice->StretchRect(source, nullptr, dest, nullptr, 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::OutOfMemory() << "Failed to blit internal texture, " << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +RendererClass Renderer9::getRendererClass() const +{ + return RENDERER_D3D9; } ImageD3D *Renderer9::createImage() @@ -2659,18 +2902,34 @@ ImageD3D *Renderer9::createImage() return new Image9(this); } -gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src) +gl::Error Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src) { Image9 *src9 = GetAs<Image9>(src); Image9 *dst9 = GetAs<Image9>(dest); return Image9::generateMipmap(dst9, src9); } -gl::Error Renderer9::generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) +gl::Error Renderer9::generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) { UNREACHABLE(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error Renderer9::copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + Image9 *dest9 = GetAs<Image9>(dest); + Image9 *src9 = GetAs<Image9>(source); + return Image9::CopyImage(context, dest9, src9, sourceRect, destOffset, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha); } TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) @@ -2679,59 +2938,83 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) return new TextureStorage9_2D(this, swapChain9); } -TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage) +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) { - return new TextureStorage9_EGLImage(this, eglImage); + UNIMPLEMENTED(); + return nullptr; } -TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +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) +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) { - return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, 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) +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; + return nullptr; } -TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +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; + return nullptr; } -TextureImpl *Renderer9::createTexture(GLenum target) +TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) { - switch(target) - { - case GL_TEXTURE_2D: return new TextureD3D_2D(this); - case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); - default: UNREACHABLE(); - } + // 2D multisampled textures are not supported by the D3D9 backend. + UNREACHABLE(); return NULL; } -RenderbufferImpl *Renderer9::createRenderbuffer() -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - return renderbuffer; -} - bool Renderer9::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; + adapterLuid->LowPart = 0; if (mD3d9Ex) { @@ -2752,6 +3035,40 @@ GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType) return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType; } +gl::ErrorOrResult<unsigned int> Renderer9::getVertexSpaceRequired(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const +{ + if (!attrib.enabled) + { + return 16u; + } + + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = + d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType); + + unsigned int elementCount = 0; + const unsigned int divisor = binding.getDivisor(); + if (instances == 0 || divisor == 0) + { + elementCount = static_cast<unsigned int>(count); + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor); + } + + if (d3d9VertexInfo.outputElementSize > std::numeric_limits<unsigned int>::max() / elementCount) + { + return gl::OutOfMemory() << "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, @@ -2761,31 +3078,11 @@ void Renderer9::generateCaps(gl::Caps *outCaps, outExtensions, outLimitations); } -WorkaroundsD3D Renderer9::generateWorkarounds() const +angle::WorkaroundsD3D Renderer9::generateWorkarounds() const { return d3d9::GenerateWorkarounds(); } -void Renderer9::createAnnotator() -{ - mAnnotator = new DebugAnnotator9(); -} - -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) @@ -2803,14 +3100,211 @@ egl::Error Renderer9::getEGLDevice(DeviceImpl **device) } *device = static_cast<DeviceImpl *>(mEGLDevice); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } Renderer9::CurSamplerState::CurSamplerState() - : forceSet(true), - baseLevel(std::numeric_limits<size_t>::max()), - samplerState() + : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState() +{ +} + +gl::Error Renderer9::genericDrawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + 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(applyTextures(context)); + ANGLE_TRY(applyShaders(context, mode)); + + if (!skipDraw(data.getState(), mode)) + { + ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances)); + } + + return gl::NoError(); +} + +gl::Error Renderer9::genericDrawArrays(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances) +{ + 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(applyVertexBuffer(context, mode, first, count, instances, nullptr)); + ANGLE_TRY(applyTextures(context)); + ANGLE_TRY(applyShaders(context, mode)); + + if (!skipDraw(context->getGLState(), mode)) + { + ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances)); + } + + 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); +} + +gl::Error Renderer9::clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) +{ + D3DCOLOR color = + D3DCOLOR_ARGB(gl::unorm<8>(clearColorValue.alpha), gl::unorm<8>(clearColorValue.red), + gl::unorm<8>(clearColorValue.green), gl::unorm<8>(clearColorValue.blue)); + float depth = clearDepthValue; + DWORD stencil = clearStencilValue & 0x000000FF; + + unsigned int renderTargetSerial = renderTarget->getSerial(); + RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget); + IDirect3DSurface9 *renderTargetSurface = renderTarget9->getSurface(); + ASSERT(renderTargetSurface); + + DWORD dxClearFlags = 0; + + const gl::InternalFormat &internalFormatInfo = + gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat()); + if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0) + { + dxClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL; + if (mAppliedDepthStencilSerial != renderTargetSerial) + { + mDevice->SetDepthStencilSurface(renderTargetSurface); + } + } + else + { + dxClearFlags = D3DCLEAR_TARGET; + if (mAppliedRenderTargetSerial != renderTargetSerial) + { + mDevice->SetRenderTarget(0, renderTargetSurface); + } + } + SafeRelease(renderTargetSurface); + + D3DVIEWPORT9 viewport; + viewport.X = 0; + viewport.Y = 0; + viewport.Width = renderTarget->getWidth(); + viewport.Height = renderTarget->getHeight(); + mDevice->SetViewport(&viewport); + + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + + mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil); + + markAllStateDirty(); + + return gl::NoError(); } + +bool Renderer9::canSelectViewInVertexShader() const +{ + return false; +} + +// 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 Renderer9::applyTextures(const gl::Context *context, gl::SamplerType shaderType) +{ + const auto &glState = context->getGLState(); + const auto &caps = context->getCaps(); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); + + ASSERT(!programD3D->isSamplerMappingDirty()); + + // TODO(jmadill): Use the Program's sampler bindings. + const auto &completeTextures = glState.getCompleteTextureCache(); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); + for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); + ASSERT(textureUnit != -1); + gl::Texture *texture = completeTextures[textureUnit]; + + // A nullptr texture indicates incomplete. + if (texture) + { + gl::Sampler *samplerObject = glState.getSampler(textureUnit); + + const gl::SamplerState &samplerState = + samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); + + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState)); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture)); + } + else + { + GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); + + // Texture is not sampler complete or it is in use by the framebuffer. Bind the + // incomplete texture. + gl::Texture *incompleteTexture = nullptr; + ANGLE_TRY(getIncompleteTexture(context, textureType, &incompleteTexture)); + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState())); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture)); + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits + : caps.maxVertexTextureImageUnits; + + // TODO(jmadill): faster way? + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) + { + ANGLE_TRY(setTexture(context, shaderType, static_cast<int>(samplerIndex), nullptr)); + } + + return gl::NoError(); +} + +gl::Error Renderer9::applyTextures(const gl::Context *context) +{ + ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX)); + ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h index a0dfecb02e..9ddee45f0f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -12,12 +12,13 @@ #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/RendererD3D.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/d3d/d3d9/VertexDeclarationCache.h" +#include "libANGLE/renderer/driver_utils.h" namespace gl { @@ -32,6 +33,7 @@ class AttributeMap; namespace rx { class Blit9; +class Context9; class IndexDataManager; class ProgramD3D; class StreamingIndexBufferInterface; @@ -65,184 +67,270 @@ class Renderer9 : public RendererD3D { public: explicit Renderer9(egl::Display *display); - virtual ~Renderer9(); + ~Renderer9() override; egl::Error initialize() override; - virtual bool resetDevice(); + bool resetDevice() override; - egl::ConfigSet generateConfigs() const override; + egl::ConfigSet generateConfigs() override; void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; void startScene(); void endScene(); - gl::Error flush() override; - gl::Error finish() override; + gl::Error flush(); + gl::Error finish(); - SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + 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; - - CompilerImpl *createCompiler() override; + EGLint orientation, + EGLint samples) override; + egl::Error getD3DTextureInfo(const egl::Config *configuration, + 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); + 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); + 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); - virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - gl::Error setUniformBuffers(const gl::Data &data, - const std::vector<GLint> &vertexUniformBuffers, - const std::vector<GLint> &fragmentUniformBuffers) override; - - gl::Error updateState(const gl::Data &data, GLenum drawMode) override; + HRESULT createIndexBuffer(UINT Length, + DWORD Usage, + D3DFORMAT Format, + IDirect3DIndexBuffer9 **ppIndexBuffer); + gl::Error setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &sampler); + gl::Error setTexture(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture); + + gl::Error updateState(const gl::Context *context, GLenum drawMode); void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - void setViewport(const gl::Caps *caps, - const gl::Rectangle &viewport, + void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport); - gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorAttachment, + gl::Error applyRenderTarget(const gl::Context *context, const gl::Framebuffer *frameBuffer); + gl::Error applyRenderTarget(const gl::Context *context, + const gl::FramebufferAttachment *colorAttachment, const gl::FramebufferAttachment *depthStencilAttachment); - gl::Error applyUniforms(const ProgramD3D &programD3D, - GLenum drawMode, - const std::vector<D3DUniform *> &uniformArray) override; - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); - virtual gl::Error applyVertexBuffer(const gl::State &state, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances, - TranslatedIndexData *indexInfo); - gl::Error applyIndexBuffer(const gl::Data &data, - const GLvoid *indices, + gl::Error applyUniforms(ProgramD3D *programD3D); + bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); + gl::Error applyVertexBuffer(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo); + gl::Error applyIndexBuffer(const gl::Context *context, + const void *indices, GLsizei count, GLenum mode, GLenum type, - TranslatedIndexData *indexInfo) override; + TranslatedIndexData *indexInfo); - void applyTransformFeedbackBuffers(const gl::State &state) override; - - gl::Error clear(const ClearParameters &clearParams, + gl::Error clear(const gl::Context *context, + const ClearParameters &clearParams, const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer); - virtual void markAllStateDirty(); + void markAllStateDirty(); // lost device bool testDeviceLost() override; bool testDeviceResettable() override; VendorID getVendorId() const; - std::string getRendererDescription() const override; + std::string getRendererDescription() const; DeviceIdentifier getAdapterIdentifier() const override; IDirect3DDevice9 *getDevice() { return mDevice; } void *getD3DDevice() override; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getReservedVertexUniformBuffers() const; - virtual unsigned int getReservedFragmentUniformBuffers() const; + unsigned int getReservedVertexUniformVectors() const; + unsigned int getReservedFragmentUniformVectors() const; bool getShareHandleSupport() const; - virtual int getMajorShaderModel() const; + int getMajorShaderModel() const override; int getMinorShaderModel() const override; std::string getShaderModelSuffix() const override; DWORD getCapsDeclTypes() 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); - virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyImage2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImageCube(const gl::Context *context, + 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::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImage2DArray(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + + gl::Error copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + gl::Error copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) override; // RenderTarget creation - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + gl::Error createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) override; gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; - // Framebuffer creation - FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; - - // Shader creation - ShaderImpl *createShader(const gl::Shader::Data &data) override; - ProgramImpl *createProgram(const gl::Program::Data &data) override; - // Shader operations - gl::Error loadExecutable(const void *function, + gl::Error loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) override; gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector<D3DVarying> &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) override; + gl::Error ensureHLSLCompilerInitialized() override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations - virtual ImageD3D *createImage(); - gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; - gl::Error generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) override; - virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); - TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override; - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - - // Texture creation - virtual TextureImpl *createTexture(GLenum target); - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer(); + ImageD3D *createImage() override; + gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) override; + gl::Error copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) 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; + + TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) override; // Buffer creation - virtual BufferImpl *createBuffer(); - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); + VertexBuffer *createVertexBuffer() override; + IndexBuffer *createIndexBuffer() override; - // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceNVImpl *createFenceNV(); - virtual FenceSyncImpl *createFenceSync(); - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback(); + // Stream Creation + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - - void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; + bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override; + gl::Error fastCopyBufferToTexture(const gl::Context *context, + 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); @@ -250,42 +338,82 @@ class Renderer9 : public RendererD3D D3DPOOL getTexturePool(DWORD usage) const; bool getLUID(LUID *adapterLuid) const override; - VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + VertexConversionType getVertexConversionType( + gl::VertexFormatType vertexFormatType) const override; GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; - gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. + gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const override; - RendererClass getRendererClass() const override { return RENDERER_D3D9; } + gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, + IDirect3DSurface9 *source, + bool fromManaged); + + RendererClass getRendererClass() const override; D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; } egl::Error getEGLDevice(DeviceImpl **device) override; - protected: - void createAnnotator() override; - gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; - gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override; + StateManager9 *getStateManager() { return &mStateManager; } + + gl::Error genericDrawArrays(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances); + + gl::Error genericDrawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances); + + // Necessary hack for default framebuffers in D3D. + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + DebugAnnotator9 *getAnnotator() { return &mAnnotator; } + + gl::Version getMaxSupportedESVersion() const override; + + gl::Error clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) override; + + bool canSelectViewInVertexShader() const override; private: - gl::Error drawArraysImpl(const gl::Data &data, + gl::Error drawArraysImpl(const gl::Context *context, GLenum mode, + GLint startVertex, GLsizei count, - GLsizei instances) override; - gl::Error drawElementsImpl(const gl::Data &data, - const TranslatedIndexData &indexInfo, + GLsizei instances); + gl::Error drawElementsImpl(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, - GLsizei instances) override; + const void *indices, + GLsizei instances); - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Error applyShaders(const gl::Context *context, GLenum drawMode); + + gl::Error applyTextures(const gl::Context *context); + gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType); + + void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions, gl::Limitations *outLimitations) const override; - WorkaroundsD3D generateWorkarounds() const override; + angle::WorkaroundsD3D generateWorkarounds() const override; - gl::Error setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode); + gl::Error setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode); void release(); @@ -293,18 +421,30 @@ class Renderer9 : public RendererD3D 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 drawLineLoop(const gl::Context *context, + GLsizei count, + GLenum type, + const void *indices, + int minIndex, + gl::Buffer *elementArrayBuffer); + gl::Error drawIndexedPoints(const gl::Context *context, + GLsizei count, + GLenum type, + const void *indices, + int minIndex, + gl::Buffer *elementArrayBuffer); gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); - gl::Error getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer); + gl::Error getNullColorbuffer(const gl::Context *context, + const gl::FramebufferAttachment *depthbuffer, + const gl::FramebufferAttachment **outColorBuffer); D3DPOOL getBufferPool(DWORD usage) const; HMODULE mD3d9Module; - void initializeDevice(); + egl::Error initializeDevice(); D3DPRESENT_PARAMETERS getDefaultPresentParameters(); void releaseDeviceResources(); @@ -314,7 +454,7 @@ class Renderer9 : public RendererD3D UINT mAdapter; D3DDEVTYPE mDeviceType; - IDirect3D9 *mD3d9; // Always valid after successful initialization. + 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. @@ -368,7 +508,7 @@ class Renderer9 : public RendererD3D unsigned int mAppliedProgramSerial; // A pool of event queries that are currently unused. - std::vector<IDirect3DQuery9*> mEventQueryPool; + std::vector<IDirect3DQuery9 *> mEventQueryPool; VertexShaderCache mVertexShaderCache; PixelShaderCache mPixelShaderCache; @@ -379,7 +519,10 @@ class Renderer9 : public RendererD3D StreamingIndexBufferInterface *mLineLoopIB; StaticIndexBufferInterface *mCountingIB; - enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + enum + { + NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 + }; struct NullColorbufferCacheEntry { UINT lruCount; @@ -390,7 +533,11 @@ class Renderer9 : public RendererD3D UINT mMaxNullColorbufferLRU; DeviceD3D *mEGLDevice; + std::vector<TranslatedAttribute> mTranslatedAttribCache; + + DebugAnnotator9 mAnnotator; }; -} -#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h index cf831c62fa..399770dd8d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h @@ -24,9 +24,7 @@ template <typename ShaderObject> class ShaderCache : angle::NonCopyable { public: - ShaderCache() : mDevice(NULL) - { - } + ShaderCache() : mDevice(nullptr) {} ~ShaderCache() { @@ -47,14 +45,14 @@ class ShaderCache : angle::NonCopyable { it->second->AddRef(); *outShaderObject = it->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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); + return gl::OutOfMemory() << "Failed to create shader, " << gl::FmtHR(result); } // Random eviction policy. @@ -68,7 +66,7 @@ class ShaderCache : angle::NonCopyable mMap[key] = shader; *outShaderObject = shader; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void clear() diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp index 28a486056b..362c6c60a3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -18,14 +18,14 @@ ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirec : ShaderExecutableD3D(function, length) { mPixelExecutable = executable; - mVertexExecutable = NULL; + mVertexExecutable = nullptr; } ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) : ShaderExecutableD3D(function, length) { mVertexExecutable = executable; - mPixelExecutable = NULL; + mPixelExecutable = nullptr; } ShaderExecutable9::~ShaderExecutable9() @@ -44,4 +44,4 @@ IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const return mPixelExecutable; } -}
\ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h index 382a68c820..0b6b87947e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h @@ -20,7 +20,7 @@ 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(); + ~ShaderExecutable9() override; IDirect3DPixelShader9 *getPixelShader() const; IDirect3DVertexShader9 *getVertexShader() const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp index c4c600aedb..a3bdc14efb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp @@ -7,7 +7,7 @@ // StateManager9.cpp: Defines a class for caching D3D9 state #include "libANGLE/renderer/d3d/d3d9/StateManager9.h" -#include "common/BitSetIterator.h" +#include "common/bitset_utils.h" #include "common/utilities.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" @@ -18,7 +18,8 @@ namespace rx { StateManager9::StateManager9(Renderer9 *renderer9) - : mCurBlendState(), + : mUsingZeroColorMaskWorkaround(false), + mCurBlendState(), mCurBlendColor(0, 0, 0, 0), mCurSampleMask(0), mCurRasterState(), @@ -67,6 +68,11 @@ StateManager9::~StateManager9() { } +void StateManager9::initialize() +{ + mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId()); +} + void StateManager9::forceSetBlendState() { mDirtyBits |= mBlendStateDirtyBits; @@ -114,7 +120,7 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits return; } - for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + for (auto dirtyBit : dirtyBits) { switch (dirtyBit) { @@ -125,6 +131,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits // 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: @@ -138,6 +150,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits 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; } @@ -148,6 +166,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits 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; } @@ -167,6 +191,14 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits 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; } @@ -364,7 +396,7 @@ gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, mCurFrontFaceCCW = frontFaceCCW; } - for (auto dirtyBit : angle::IterateBitSet(mDirtyBits)) + for (auto dirtyBit : mDirtyBits) { switch (dirtyBit) { @@ -438,11 +470,10 @@ gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, setSampleMask(sampleMask); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void StateManager9::setViewportState(const gl::Caps *caps, - const gl::Rectangle &viewport, +void StateManager9::setViewportState(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, @@ -698,6 +729,7 @@ void StateManager9::setStencilTestEnabled(bool stencilTestEnabled) if (stencilTestEnabled && mCurStencilSize > 0) { mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); } else { @@ -718,7 +750,7 @@ void StateManager9::setSampleAlphaToCoverage(bool enabled) { if (enabled) { - FIXME("Sample alpha to coverage is unimplemented."); + UNREACHABLE(); } } @@ -800,42 +832,52 @@ void StateManager9::setColorMask(const gl::Framebuffer *framebuffer, bool alpha) { // Set the color mask - bool zeroColorMaskAllowed = mRenderer9->getVendorId() != VENDOR_ID_AMD; - // 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://code.google.com/p/angleproject/issues/detail?id=169 - const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); - GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + const auto *attachment = framebuffer->getFirstColorbuffer(); + const auto &format = attachment ? attachment->getFormat() : gl::Format::Invalid(); DWORD colorMask = gl_d3d9::ConvertColorMask( - formatInfo.redBits > 0 && red, formatInfo.greenBits > 0 && green, - formatInfo.blueBits > 0 && blue, formatInfo.alphaBits > 0 && alpha); - - if (colorMask == 0 && !zeroColorMaskAllowed) + 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; + mCurBlendState.colorMaskRed = red; + mCurBlendState.colorMaskGreen = green; + mCurBlendState.colorMaskBlue = blue; + mCurBlendState.colorMaskAlpha = alpha; + } } void StateManager9::setSampleMask(unsigned int sampleMask) @@ -848,7 +890,7 @@ void StateManager9::setSampleMask(unsigned int sampleMask) mCurSampleMask = sampleMask; } -void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace) +void StateManager9::setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace) { if (cullFace) { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h index d8c1eb9812..63ce17cb1e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h @@ -10,7 +10,7 @@ #define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ #include "libANGLE/angletypes.h" -#include "libANGLE/Data.h" +#include "libANGLE/ContextState.h" #include "libANGLE/State.h" #include "libANGLE/renderer/d3d/RendererD3D.h" @@ -39,12 +39,13 @@ class StateManager9 final : angle::NonCopyable 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::Caps *caps, - const gl::Rectangle &viewport, + void setViewportState(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, @@ -85,7 +86,7 @@ class StateManager9 final : angle::NonCopyable void setSampleMask(unsigned int sampleMask); // Current raster state functions - void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace); + void setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace); void setDepthBias(bool polygonOffsetFill, GLfloat polygonOffsetFactor, GLfloat polygonOffsetUnits); @@ -154,7 +155,9 @@ class StateManager9 final : angle::NonCopyable DIRTY_BIT_MAX }; - typedef std::bitset<DIRTY_BIT_MAX> DirtyBits; + using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; + + bool mUsingZeroColorMaskWorkaround; // Currently applied blend state gl::BlendState mCurBlendState; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp index be6a9c424c..bc81aa18ec 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -7,25 +7,29 @@ // 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/features.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" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" namespace rx { SwapChain9::SwapChain9(Renderer9 *renderer, - NativeWindow nativeWindow, + NativeWindow9 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, EGLint orientation) - : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat), mRenderer(renderer), mWidth(-1), mHeight(-1), mSwapInterval(-1), + mNativeWindow(nativeWindow), mSwapChain(nullptr), mBackBuffer(nullptr), mRenderTarget(nullptr), @@ -50,9 +54,9 @@ void SwapChain9::release() SafeRelease(mRenderTarget); SafeRelease(mOffscreenTexture); - if (mNativeWindow.getNativeWindow()) + if (mNativeWindow->getNativeWindow()) { - mShareHandle = NULL; + mShareHandle = nullptr; } } @@ -75,17 +79,20 @@ static DWORD convertInterval(EGLint interval) #endif } -EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +EGLint SwapChain9::resize(const gl::Context *context, int backbufferWidth, int backbufferHeight) { // D3D9 does not support resizing swap chains without recreating them - return reset(backbufferWidth, backbufferHeight, mSwapInterval); + return reset(context, backbufferWidth, backbufferHeight, mSwapInterval); } -EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +EGLint SwapChain9::reset(const gl::Context *context, + int backbufferWidth, + int backbufferHeight, + EGLint swapInterval) { IDirect3DDevice9 *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { return EGL_BAD_ACCESS; } @@ -103,28 +110,37 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI SafeRelease(mOffscreenTexture); SafeRelease(mDepthStencil); - HANDLE *pShareHandle = NULL; - if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport()) + const d3d9::TextureFormat &backBufferd3dFormatInfo = + d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat); + if (mD3DTexture != nullptr) { - pShareHandle = &mShareHandle; + result = mD3DTexture->QueryInterface(&mOffscreenTexture); + ASSERT(SUCCEEDED(result)); } - - const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat); - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, - pShareHandle); - if (FAILED(result)) + else { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if (d3d9::isDeviceLostError(result)) + HANDLE *pShareHandle = nullptr; + if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport()) { - return EGL_CONTEXT_LOST; + pShareHandle = &mShareHandle; } - else + + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, + &mOffscreenTexture, pShareHandle); + if (FAILED(result)) { - return EGL_BAD_ALLOC; + ERR() << "Could not create offscreen texture, " << gl::FmtHR(result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } } } @@ -163,7 +179,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI // Don't create a swapchain for NULLREF devices D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType(); - EGLNativeWindowType window = mNativeWindow.getNativeWindow(); + EGLNativeWindowType window = mNativeWindow->getNativeWindow(); if (window && deviceType != D3DDEVTYPE_NULLREF) { D3DPRESENT_PARAMETERS presentParameters = {0}; @@ -189,7 +205,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI // // 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 (mRenderer->getVendorId() == VENDOR_ID_INTEL) + if (IsIntel(mRenderer->getVendorId())) { presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; } @@ -200,7 +216,8 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI { 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); + ERR() << "Could not create additional swap chains or offscreen surfaces, " + << gl::FmtHR(result); release(); if (d3d9::isDeviceLostError(result)) @@ -215,20 +232,21 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); ASSERT(SUCCEEDED(result)); - InvalidateRect(window, NULL, FALSE); + InvalidateRect(window, nullptr, FALSE); } if (mDepthBufferFormat != GL_NONE) { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - depthBufferd3dFormatInfo.renderFormat, - D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + result = device->CreateDepthStencilSurface( + backbufferWidth, backbufferHeight, depthBufferd3dFormatInfo.renderFormat, + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, nullptr); 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); + ERR() << "Could not create depthstencil surface for new swap chain, " + << gl::FmtHR(result); release(); if (d3d9::isDeviceLostError(result)) @@ -250,7 +268,11 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI } // parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain9::swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { @@ -270,11 +292,11 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) 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->SetPixelShader(nullptr); + device->SetVertexShader(nullptr); device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); + device->SetDepthStencilSurface(nullptr); device->SetTexture(0, mOffscreenTexture); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); @@ -313,7 +335,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); mRenderer->endScene(); - device->SetTexture(0, NULL); + device->SetTexture(0, nullptr); RECT rect = { @@ -321,7 +343,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y) }; - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + HRESULT result = mSwapChain->Present(&rect, &rect, nullptr, nullptr, 0); mRenderer->markAllStateDirty(); @@ -333,7 +355,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) // 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 == 0x88760873) + if (result == static_cast<HRESULT>(0x88760873)) { return EGL_BAD_MATCH; } @@ -395,6 +417,12 @@ void *SwapChain9::getKeyedMutex() return nullptr; } +egl::Error SwapChain9::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) +{ + UNREACHABLE(); + return egl::EglBadSurface(); +} + void SwapChain9::recreate() { if (!mSwapChain) @@ -403,7 +431,7 @@ void SwapChain9::recreate() } IDirect3DDevice9 *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { return; } @@ -412,7 +440,7 @@ void SwapChain9::recreate() HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); ASSERT(SUCCEEDED(result)); - IDirect3DSwapChain9* newSwapChain = NULL; + IDirect3DSwapChain9 *newSwapChain = nullptr; result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); if (FAILED(result)) { @@ -427,4 +455,13 @@ void SwapChain9::recreate() ASSERT(SUCCEEDED(result)); } +RenderTargetD3D *SwapChain9::getColorRenderTarget() +{ + return &mColorRenderTarget; +} + +RenderTargetD3D *SwapChain9::getDepthStencilRenderTarget() +{ + return &mDepthStencilRenderTarget; +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h index 55a700c2d6..5753637c47 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -15,26 +15,36 @@ namespace rx { +class NativeWindow9; class Renderer9; class SwapChain9 : public SwapChainD3D { public: SwapChain9(Renderer9 *renderer, - NativeWindow nativeWindow, + NativeWindow9 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, EGLint orientation); - virtual ~SwapChain9(); + ~SwapChain9() override; - 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(); + EGLint resize(const gl::Context *context, EGLint backbufferWidth, EGLint backbufferHeight) + override; + EGLint reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) override; + EGLint swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) override; + void recreate() override; - RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } - RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + RenderTargetD3D *getColorRenderTarget() override; + RenderTargetD3D *getDepthStencilRenderTarget() override; virtual IDirect3DSurface9 *getRenderTarget(); virtual IDirect3DSurface9 *getDepthStencil(); @@ -45,6 +55,8 @@ class SwapChain9 : public SwapChainD3D void *getKeyedMutex() override; + egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; + private: void release(); @@ -53,6 +65,8 @@ class SwapChain9 : public SwapChainD3D EGLint mHeight; EGLint mSwapInterval; + NativeWindow9 *mNativeWindow; + IDirect3DSwapChain9 *mSwapChain; IDirect3DSurface9 *mBackBuffer; IDirect3DSurface9 *mRenderTarget; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp index b28d5076b5..6404af6bba 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -43,7 +43,7 @@ DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) { DWORD d3dusage = 0; - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { @@ -93,11 +93,16 @@ 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) +gl::Error TextureStorage9::setData(const gl::Context *context, + 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); + return gl::InternalError(); } TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain) @@ -107,7 +112,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai mTexture = surfaceTexture; mMipLevels = surfaceTexture->GetLevelCount(); - mInternalFormat = swapchain->GetRenderTargetInternalFormat(); + mInternalFormat = swapchain->getRenderTargetInternalFormat(); D3DSURFACE_DESC surfaceDesc; surfaceTexture->GetLevelDesc(0, &surfaceDesc); @@ -121,7 +126,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { - mTexture = NULL; + mTexture = nullptr; mInternalFormat = internalformat; @@ -139,7 +144,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalforma TextureStorage9_2D::~TextureStorage9_2D() { SafeRelease(mTexture); - for (auto &renderTarget : mRenderTargets) + for (RenderTargetD3D *renderTarget : mRenderTargets) { SafeDelete(renderTarget); } @@ -147,16 +152,16 @@ TextureStorage9_2D::~TextureStorage9_2D() // Increments refcount on surface. // caller must Release() the returned surface -gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target, +gl::Error TextureStorage9_2D::getSurfaceLevel(const gl::Context *context, + GLenum target, int level, bool dirty, IDirect3DSurface9 **outSurface) { ASSERT(target == GL_TEXTURE_2D); - UNUSED_ASSERTION_VARIABLE(target); - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); + IDirect3DBaseTexture9 *baseTexture = nullptr; + gl::Error error = getBaseTexture(context, &baseTexture); if (error.isError()) { return error; @@ -169,33 +174,36 @@ gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target, 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); + return gl::OutOfMemory() << "Failed to get the surface from a texture, " + << gl::FmtHR(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); + texture->AddDirtyRect(nullptr); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage9_2D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(index.mipIndex < getLevelCount()); if (!mRenderTargets[index.mipIndex] && isRenderTarget()) { - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); + IDirect3DBaseTexture9 *baseTexture = nullptr; + gl::Error error = getBaseTexture(context, &baseTexture); if (error.isError()) { return error; } - IDirect3DSurface9 *surface = NULL; - error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface); + IDirect3DSurface9 *surface = nullptr; + error = getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, false, &surface); if (error.isError()) { return error; @@ -213,20 +221,22 @@ gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, Rende ASSERT(outRT); *outRT = mRenderTargets[index.mipIndex]; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +gl::Error TextureStorage9_2D::generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) { - IDirect3DSurface9 *upper = NULL; - gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper); + IDirect3DSurface9 *upper = nullptr; + gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper); if (error.isError()) { return error; } - IDirect3DSurface9 *lower = NULL; - error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower); + IDirect3DSurface9 *lower = nullptr; + error = getSurfaceLevel(context, GL_TEXTURE_2D, destIndex.mipIndex, true, &lower); if (error.isError()) { SafeRelease(upper); @@ -242,32 +252,34 @@ gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, return error; } -gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +gl::Error TextureStorage9_2D::getBaseTexture(const gl::Context *context, + 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) + if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mMipLevels > 0); IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth), + HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mTextureHeight), static_cast<unsigned int>(mMipLevels), getUsage(), - mTextureFormat, getPool(), &mTexture, NULL); + mTextureFormat, getPool(), &mTexture, nullptr); 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); + return gl::OutOfMemory() + << "Failed to create 2D storage texture, " << gl::FmtHR(result); } } *outTexture = mTexture; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage9_2D::copyToStorage(const gl::Context *context, TextureStorage *destStorage) { ASSERT(destStorage); @@ -276,15 +288,15 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) int levels = getLevelCount(); for (int i = 0; i < levels; ++i) { - IDirect3DSurface9 *srcSurf = NULL; - gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf); + IDirect3DSurface9 *srcSurf = nullptr; + gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, i, false, &srcSurf); if (error.isError()) { return error; } - IDirect3DSurface9 *dstSurf = NULL; - error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf); + IDirect3DSurface9 *dstSurf = nullptr; + error = dest9->getSurfaceLevel(context, GL_TEXTURE_2D, i, true, &dstSurf); if (error.isError()) { SafeRelease(srcSurf); @@ -302,17 +314,14 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image) +TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer, + EGLImageD3D *image, + RenderTarget9 *renderTarget9) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image) { - RenderTargetD3D *renderTargetD3D = nullptr; - mImage->getRenderTarget(&renderTargetD3D); - - RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D); - mInternalFormat = renderTarget9->getInternalFormat(); mTextureFormat = renderTarget9->getD3DFormat(); mTextureWidth = renderTarget9->getWidth(); @@ -325,18 +334,17 @@ TextureStorage9_EGLImage::~TextureStorage9_EGLImage() { } -gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target, +gl::Error TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context, + GLenum target, int level, bool, IDirect3DSurface9 **outSurface) { ASSERT(target == GL_TEXTURE_2D); ASSERT(level == 0); - UNUSED_ASSERTION_VARIABLE(target); - UNUSED_ASSERTION_VARIABLE(level); RenderTargetD3D *renderTargetD3D = nullptr; - gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D); if (error.isError()) { return error; @@ -345,23 +353,24 @@ gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target, RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D); *outSurface = renderTarget9->getSurface(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index, +gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); ASSERT(index.mipIndex == 0); - UNUSED_ASSERTION_VARIABLE(index); - return mImage->getRenderTarget(outRT); + return mImage->getRenderTarget(context, outRT); } -gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +gl::Error TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context, + IDirect3DBaseTexture9 **outTexture) { RenderTargetD3D *renderTargetD3D = nullptr; - gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D); if (error.isError()) { return error; @@ -371,16 +380,19 @@ gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTe *outTexture = renderTarget9->getTexture(); ASSERT(*outTexture != nullptr); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &) +gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::Context *context, + const gl::ImageIndex &, + const gl::ImageIndex &) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage9_EGLImage::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); ASSERT(getLevelCount() == 1); @@ -388,7 +400,7 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage); IDirect3DBaseTexture9 *destBaseTexture9 = nullptr; - gl::Error error = dest9->getBaseTexture(&destBaseTexture9); + gl::Error error = dest9->getBaseTexture(context, &destBaseTexture9); if (error.isError()) { return error; @@ -400,12 +412,12 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) 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); + return gl::OutOfMemory() << "Failed to get the surface from a texture, " + << gl::FmtHR(result); } RenderTargetD3D *sourceRenderTarget = nullptr; - error = mImage->getRenderTarget(&sourceRenderTarget); + error = mImage->getRenderTarget(context, &sourceRenderTarget); if (error.isError()) { SafeRelease(destSurface); @@ -427,16 +439,16 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) } SafeRelease(destSurface); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { - mTexture = NULL; - for (int i = 0; i < CUBE_FACE_COUNT; ++i) + mTexture = nullptr; + for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i) { - mRenderTarget[i] = NULL; + mRenderTarget[i] = nullptr; } mInternalFormat = internalformat; @@ -455,7 +467,7 @@ TextureStorage9_Cube::~TextureStorage9_Cube() { SafeRelease(mTexture); - for (int i = 0; i < CUBE_FACE_COUNT; ++i) + for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i) { SafeDelete(mRenderTarget[i]); } @@ -463,13 +475,14 @@ TextureStorage9_Cube::~TextureStorage9_Cube() // Increments refcount on surface. // caller must Release() the returned surface -gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target, +gl::Error TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context, + GLenum target, int level, bool dirty, IDirect3DSurface9 **outSurface) { - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); + IDirect3DBaseTexture9 *baseTexture = nullptr; + gl::Error error = getBaseTexture(context, &baseTexture); if (error.isError()) { return error; @@ -483,35 +496,38 @@ gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target, 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); + return gl::OutOfMemory() << "Failed to get the surface from a texture, " + << gl::FmtHR(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); + texture->AddDirtyRect(face, nullptr); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(outRT); ASSERT(index.mipIndex == 0); - ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT); + ASSERT(index.layerIndex >= 0 && static_cast<size_t>(index.layerIndex) < gl::CUBE_FACE_COUNT); - if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) + if (mRenderTarget[index.layerIndex] == nullptr && isRenderTarget()) { - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); + IDirect3DBaseTexture9 *baseTexture = nullptr; + gl::Error error = getBaseTexture(context, &baseTexture); if (error.isError()) { return error; } - IDirect3DSurface9 *surface = NULL; - error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, + IDirect3DSurface9 *surface = nullptr; + error = getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, mTopLevel + index.mipIndex, false, &surface); if (error.isError()) { @@ -525,20 +541,23 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren } *outRT = mRenderTarget[index.layerIndex]; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +gl::Error TextureStorage9_Cube::generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) { - IDirect3DSurface9 *upper = NULL; - gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + IDirect3DSurface9 *upper = nullptr; + gl::Error error = + getSurfaceLevel(context, sourceIndex.type, sourceIndex.mipIndex, false, &upper); if (error.isError()) { return error; } - IDirect3DSurface9 *lower = NULL; - error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower); + IDirect3DSurface9 *lower = nullptr; + error = getSurfaceLevel(context, destIndex.type, destIndex.mipIndex, true, &lower); if (error.isError()) { SafeRelease(upper); @@ -554,52 +573,56 @@ gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex return error; } -gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +gl::Error TextureStorage9_Cube::getBaseTexture(const gl::Context *context, + 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) + if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mMipLevels > 0); ASSERT(mTextureWidth == mTextureHeight); IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateCubeTexture( + HRESULT result = device->CreateCubeTexture( static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels), - getUsage(), mTextureFormat, getPool(), &mTexture, NULL); + getUsage(), mTextureFormat, getPool(), &mTexture, nullptr); 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); + return gl::OutOfMemory() + << "Failed to create cube storage texture, " << gl::FmtHR(result); } } *outTexture = mTexture; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage9_Cube::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage); int levels = getLevelCount(); - for (int f = 0; f < CUBE_FACE_COUNT; f++) + for (int f = 0; f < static_cast<int>(gl::CUBE_FACE_COUNT); f++) { for (int i = 0; i < levels; i++) { - IDirect3DSurface9 *srcSurf = NULL; + IDirect3DSurface9 *srcSurf = nullptr; gl::Error error = - getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + getSurfaceLevel(context, 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); + IDirect3DSurface9 *dstSurf = nullptr; + error = dest9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, + &dstSurf); if (error.isError()) { SafeRelease(srcSurf); @@ -618,7 +641,7 @@ gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h index 50e63a6f14..2f51901931 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -25,28 +25,34 @@ class RenderTarget9; class TextureStorage9 : public TextureStorage { public: - virtual ~TextureStorage9(); + ~TextureStorage9() override; static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); D3DPOOL getPool() const; DWORD getUsage() const; - virtual gl::Error getSurfaceLevel(GLenum target, + virtual gl::Error getSurfaceLevel(const gl::Context *context, + 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 gl::Error getBaseTexture(const gl::Context *context, + IDirect3DBaseTexture9 **outTexture) = 0; - virtual int getTopLevel() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; + int getTopLevel() const override; + bool isRenderTarget() const override; + bool isManaged() const override; bool supportsNativeMipmapFunction() const override; - virtual int getLevelCount() const; + int getLevelCount() const override; - 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 setData(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) override; protected: int mTopLevel; @@ -70,16 +76,22 @@ 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(); + ~TextureStorage9_2D() override; - gl::Error getSurfaceLevel(GLenum target, + gl::Error getSurfaceLevel(const gl::Context *context, + 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); + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + gl::Error getBaseTexture(const gl::Context *context, + IDirect3DBaseTexture9 **outTexture) override; + gl::Error generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; private: IDirect3DTexture9 *mTexture; @@ -89,18 +101,23 @@ class TextureStorage9_2D : public TextureStorage9 class TextureStorage9_EGLImage final : public TextureStorage9 { public: - TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image); + TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9); ~TextureStorage9_EGLImage() override; - gl::Error getSurfaceLevel(GLenum target, + gl::Error getSurfaceLevel(const gl::Context *context, + 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, + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + gl::Error getBaseTexture(const gl::Context *context, + IDirect3DBaseTexture9 **outTexture) override; + gl::Error generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) override; - gl::Error copyToStorage(TextureStorage *destStorage) override; + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; private: EGLImageD3D *mImage; @@ -110,25 +127,28 @@ class TextureStorage9_Cube : public TextureStorage9 { public: TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); - virtual ~TextureStorage9_Cube(); + ~TextureStorage9_Cube() override; - gl::Error getSurfaceLevel(GLenum target, + gl::Error getSurfaceLevel(const gl::Context *context, + 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); + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + gl::Error getBaseTexture(const gl::Context *context, + IDirect3DBaseTexture9 **outTexture) override; + gl::Error generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; private: - static const size_t CUBE_FACE_COUNT = 6; - IDirect3DCubeTexture9 *mTexture; - RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT]; + RenderTarget9 *mRenderTarget[gl::CUBE_FACE_COUNT]; }; } #endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ - diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h index 992201737f..0f4410b8de 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -9,7 +9,9 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ #define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ +#include "libANGLE/Context.h" #include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d9/Context9.h" #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" namespace rx @@ -19,14 +21,26 @@ class Renderer9; class VertexArray9 : public VertexArrayImpl { public: - VertexArray9(const gl::VertexArray::Data &data) - : VertexArrayImpl(data) - { - } + VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {} - virtual ~VertexArray9() { } + void syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) override; + + ~VertexArray9() override {} + + Serial getCurrentStateSerial() const { return mCurrentStateSerial; } + + private: + Serial mCurrentStateSerial; }; +inline void VertexArray9::syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) +{ + ASSERT(dirtyBits.any()); + Renderer9 *renderer = GetImplAs<Context9>(context)->getRenderer(); + mCurrentStateSerial = renderer->generateSerial(); +} } #endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp index bfdf137126..c0b80a847c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -19,7 +19,7 @@ namespace rx VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer) { - mVertexBuffer = NULL; + mVertexBuffer = nullptr; mBufferSize = 0; mDynamicUsage = false; } @@ -47,16 +47,18 @@ gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); + return gl::OutOfMemory() + << "Failed to allocate internal vertex buffer of size " << size; } } mBufferSize = size; mDynamicUsage = dynamicUsage; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -66,32 +68,33 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib { if (!mVertexBuffer) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "Internal vertex buffer is not initialized."; } - int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib)); + int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib, binding)); int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib)); DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - uint8_t *mapPtr = NULL; + uint8_t *mapPtr = nullptr; - unsigned int mapSize; - gl::Error error = spaceRequired(attrib, count, instances, &mapSize); - if (error.isError()) + auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, binding, count, instances); + if (errorOrMapSize.isError()) { - return error; + 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); + return gl::OutOfMemory() << "Failed to lock internal vertex buffer, " << gl::FmtHR(result); } const uint8_t *input = sourceData; - if (instances == 0 || attrib.divisor == 0) + if (instances == 0 || binding.getDivisor() == 0) { input += inputStride * start; } @@ -112,13 +115,7 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib mVertexBuffer->Unlock(); - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - return spaceRequired(attrib, count, instances, outSpaceRequired); + return gl::NoError(); } unsigned int VertexBuffer9::getBufferSize() const @@ -134,7 +131,7 @@ gl::Error VertexBuffer9::setBufferSize(unsigned int size) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } @@ -142,7 +139,7 @@ gl::Error VertexBuffer9::discard() { if (!mVertexBuffer) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "Internal vertex buffer is not initialized."; } void *dummy; @@ -151,65 +148,22 @@ gl::Error VertexBuffer9::discard() 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); + return gl::OutOfMemory() << "Failed to lock internal buffer for discarding, " + << gl::FmtHR(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::OutOfMemory() << "Failed to unlock internal buffer for discarding, " + << gl::FmtHR(result); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const { return mVertexBuffer; } - -gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT); - const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType); - - if (attrib.enabled) - { - 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) - { - if (outSpaceRequired) - { - *outSpaceRequired = - static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount; - } - return gl::Error(GL_NO_ERROR); - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return gl::Error(GL_NO_ERROR); - } -} - -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h index 64271cbe2a..983616f4e4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h @@ -19,11 +19,13 @@ class VertexBuffer9 : public VertexBuffer { public: explicit VertexBuffer9(Renderer9 *renderer); - virtual ~VertexBuffer9(); - virtual gl::Error initialize(unsigned int size, bool dynamicUsage); + gl::Error initialize(unsigned int size, bool dynamicUsage) override; + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -31,23 +33,19 @@ class VertexBuffer9 : public VertexBuffer unsigned int offset, const uint8_t *sourceData) override; - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - - virtual unsigned int getBufferSize() const; - virtual gl::Error setBufferSize(unsigned int size); - virtual gl::Error discard(); + 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; - - gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) const; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp index a23ab4a290..abadf5c0b5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -21,7 +21,7 @@ VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) { for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) { - mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].vertexDeclaration = nullptr; mVertexDeclCache[i].lruCount = 0; } @@ -30,7 +30,7 @@ VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) mAppliedVBs[i].serial = 0; } - mLastSetVDecl = NULL; + mLastSetVDecl = nullptr; mInstancingEnabled = true; } @@ -42,11 +42,13 @@ VertexDeclarationCache::~VertexDeclarationCache() } } -gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, - const std::vector<TranslatedAttribute> &attributes, - gl::Program *program, - GLsizei instances, - GLsizei *repeatDraw) +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()); @@ -102,14 +104,14 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, D3DVERTEXELEMENT9 *element = &elements[0]; ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - const auto &semanticIndexes = programD3D->getSemanticIndexes(); + 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); + ASSERT(attributes[i].storage == nullptr); int stream = static_cast<int>(i); @@ -147,19 +149,24 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, } } - VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer); + 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 != attributes[i].offset) + mAppliedVBs[stream].offset != offset) { - device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); + device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset, + attributes[i].stride); mAppliedVBs[stream].serial = attributes[i].serial; mAppliedVBs[stream].stride = attributes[i].stride; - mAppliedVBs[stream].offset = attributes[i].offset; + mAppliedVBs[stream].offset = offset; } - gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT); + 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); @@ -200,7 +207,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, mLastSetVDecl = entry->vertexDeclaration; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } @@ -214,7 +221,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, } } - if (lastCache->vertexDeclaration != NULL) + if (lastCache->vertexDeclaration != nullptr) { SafeRelease(lastCache->vertexDeclaration); // mLastSetVDecl is set to the replacement, so we don't have to worry @@ -225,14 +232,15 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, 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); + return gl::OutOfMemory() << "Failed to create internal vertex declaration, " + << gl::FmtHR(result); } device->SetVertexDeclaration(lastCache->vertexDeclaration); mLastSetVDecl = lastCache->vertexDeclaration; lastCache->lruCount = ++mMaxLru; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void VertexDeclarationCache::markStateDirty() @@ -242,7 +250,7 @@ void VertexDeclarationCache::markStateDirty() mAppliedVBs[i].serial = 0; } - mLastSetVDecl = NULL; + mLastSetVDecl = nullptr; mInstancingEnabled = true; // Forces it to be disabled when not used } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h index bad4de4d6b..7bd7cabae4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -30,6 +30,7 @@ class VertexDeclarationCache gl::Error applyDeclaration(IDirect3DDevice9 *device, const std::vector<TranslatedAttribute> &attributes, gl::Program *program, + GLint start, GLsizei instances, GLsizei *repeatDraw); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp index b672a60e3c..d10fa1ee87 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -7,12 +7,16 @@ // formatutils9.cpp: Queries for GL image formats and their translations to D3D9 // formats. -#include "libANGLE/renderer/d3d/copyimage.h" #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" -#include "libANGLE/renderer/d3d/generatemip.h" -#include "libANGLE/renderer/d3d/loadimage.h" + +using namespace angle; namespace rx { @@ -20,35 +24,8 @@ namespace rx namespace d3d9 { -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); - -struct D3D9FastCopyFormat -{ - GLenum destFormat; - GLenum destType; - ColorCopyFunction copyFunction; - - D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) - : destFormat(destFormat), destType(destType), copyFunction(copyFunction) - { } - - bool operator<(const D3D9FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; - } -}; - -typedef std::multimap<D3DFORMAT, D3D9FastCopyFormat> D3D9FastCopyMap; - -static D3D9FastCopyMap BuildFastCopyMap() -{ - D3D9FastCopyMap map; - - map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); - - return map; -} +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; @@ -64,109 +41,188 @@ D3DFormat::D3DFormat() luminanceBits(0), depthBits(0), stencilBits(0), - internalFormat(GL_NONE), - mipGenerationFunction(NULL), - colorReadFunction(NULL), - fastCopyFunctions() + formatID(angle::Format::ID::NONE) { } -ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const +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) { - FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); - return (iter != fastCopyFunctions.end()) ? iter->second : NULL; } -static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, - GLuint blockHeight, GLuint redBits, GLuint greenBits, GLuint blueBits, - GLuint alphaBits, GLuint lumBits, GLuint depthBits, GLuint stencilBits, - GLenum internalFormat, MipGenerationFunction mipFunc, - ColorReadFunction colorReadFunc) +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) { - D3DFormat info; - info.pixelBytes = bits / 8; - info.blockWidth = blockWidth; - info.blockHeight = blockHeight; - info.redBits = redBits; - info.greenBits = greenBits; - info.blueBits = blueBits; - info.alphaBits = alphaBits; - info.luminanceBits = lumBits; - info.depthBits = depthBits; - info.stencilBits = stencilBits; - info.internalFormat = internalFormat; - info.mipGenerationFunction = mipFunc; - info.colorReadFunction = colorReadFunc; - - static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); - std::pair<D3D9FastCopyMap::const_iterator, D3D9FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(format); - for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + if (format == D3DFMT_NULL) { - info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE); + return info; } - map->insert(std::make_pair(format, info)); -} - -static D3D9FormatInfoMap BuildD3D9FormatInfoMap() -{ - D3D9FormatInfoMap map; - - // | D3DFORMAT | S |W |H | R | G | B | A | L | D | S | Internal format | Mip generation function | Color read function | - InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip<A4R4G4B4>, ReadColor<A4R4G4B4, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip<A1R5G5B5>, ReadColor<A1R5G5B5, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, 16, 0, 0, 0, 0, 0, 0, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, 16, 16, 0, 0, 0, 0, 0, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, 16, 16, 16, 16, 0, 0, 0, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>); - InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, 32, 0, 0, 0, 0, 0, 0, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, 32, 32, 0, 0, 0, 0, 0, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, 32, 32, 32, 32, 0, 0, 0, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>); - - InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, 0, 0, 0, 0, 0, 16, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, 0, 0, 0, 0, 0, 32, 0, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); - - return map; -} - -const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) -{ - static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) + if (format == D3DFMT_INTZ) { - return iter->second; + static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, Format::ID::D24_UNORM_S8_UINT); + return info; } - else + + switch (format) { - static const D3DFormat defaultInfo; - return defaultInfo; - } -} + case D3DFMT_UNKNOWN: + { + static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE); + return info; + } + case D3DFMT_L8: + { + static const D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, Format::ID::L8_UNORM); + return info; + } + case D3DFMT_A8: + { + static const D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, Format::ID::A8_UNORM); + return info; + } + case D3DFMT_A8L8: + { + static const D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, Format::ID::L8A8_UNORM); + return info; + } + case D3DFMT_A4R4G4B4: + { + static const D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0, Format::ID::B4G4R4A4_UNORM); + return info; + } + case D3DFMT_A1R5G5B5: + { + static const D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0, Format::ID::B5G5R5A1_UNORM); + return info; + } + case D3DFMT_R5G6B5: + { + static const D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0, Format::ID::R5G6B5_UNORM); + return info; + } + case D3DFMT_X8R8G8B8: + { + static const D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0, Format::ID::B8G8R8X8_UNORM); + return info; + } + case D3DFMT_A8R8G8B8: + { + static const D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0, Format::ID::B8G8R8A8_UNORM); + return info; + } + + case D3DFMT_R16F: + { + static const D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, Format::ID::R16_FLOAT); + return info; + } + case D3DFMT_G16R16F: + { + static const D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0, Format::ID::R16G16_FLOAT); + return info; + } + case D3DFMT_A16B16G16R16F: + { + static const D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0, + Format::ID::R16G16B16A16_FLOAT); + return info; + } + case D3DFMT_R32F: + { + static const D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, Format::ID::R32_FLOAT); + return info; + } + case D3DFMT_G32R32F: + { + static const D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0, Format::ID::R32G32_FLOAT); + return info; + } + case D3DFMT_A32B32G32R32F: + { + static const D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0, + Format::ID::R32G32B32A32_FLOAT); + return info; + } + + case D3DFMT_D16: + { + static const D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, Format::ID::D16_UNORM); + return info; + } + case D3DFMT_D24S8: + { + static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, + Format::ID::D24_UNORM_S8_UINT); + return info; + } + case D3DFMT_D24X8: + { + static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, Format::ID::D16_UNORM); + return info; + } + case D3DFMT_D32: + { + static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, Format::ID::D32_UNORM); + return info; + } + + case D3DFMT_DXT1: + { + static const D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC1_RGBA_UNORM_BLOCK); + return info; + } + case D3DFMT_DXT3: + { + static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC2_RGBA_UNORM_BLOCK); + return info; + } + case D3DFMT_DXT5: + { + static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0, + Format::ID::BC3_RGBA_UNORM_BLOCK); + return info; + } + + default: + { + static const 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>)); @@ -175,28 +231,6 @@ static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() return map; } -// Each GL internal format corresponds to one D3D format and data loading function. -// Due to not all formats being available all the time, some of the function/format types are wrapped -// in templates that perform format support queries on a Renderer9 object which is supplied -// when requesting the function or format. - -typedef bool(*FallbackPredicateFunction)(); - -template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback> -static void FallbackLoad(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) -{ - if (pred()) - { - prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); - } - else - { - fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); - } -} - 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) @@ -210,7 +244,7 @@ typedef std::map<GLenum, TextureFormat> D3D9FormatMap; TextureFormat::TextureFormat() : texFormat(D3DFMT_UNKNOWN), renderFormat(D3DFMT_UNKNOWN), - dataInitializerFunction(NULL), + dataInitializerFunction(nullptr), loadFunction(UnreachableLoad) { } @@ -224,7 +258,8 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalForma static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); - info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; + info.dataInitializerFunction = + (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : nullptr; info.loadFunction = loadFunction; @@ -233,8 +268,11 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalForma 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 ); @@ -268,11 +306,11 @@ static D3D9FormatMap BuildD3D9FormatMap() 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, FallbackLoad<gl::supportsSSE2, LoadA8ToBGRA8_SSE2, LoadA8ToBGRA8>); + 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, FallbackLoad<gl::supportsSSE2, LoadRGBA8ToBGRA8_SSE2, LoadRGBA8ToBGRA8>); + 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 ); @@ -291,6 +329,7 @@ static D3D9FormatMap BuildD3D9FormatMap() // then changing the format and loading function appropriately. InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> ); InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> ); + // clang-format on return map; } @@ -503,7 +542,7 @@ public: VertexFormat::VertexFormat() : conversionType(VERTEX_CONVERT_NONE), outputElementSize(0), - copyFunction(NULL), + copyFunction(nullptr), nativeFormat(D3DDECLTYPE_UNUSED), componentType(GL_NONE) { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h index c55010760d..1bef320b53 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h @@ -15,6 +15,8 @@ #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 @@ -25,11 +27,22 @@ class Renderer9; namespace d3d9 { -typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap; - struct D3DFormat { D3DFormat(); + 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; @@ -44,14 +57,9 @@ struct D3DFormat GLuint depthBits; GLuint stencilBits; - GLenum internalFormat; - - MipGenerationFunction mipGenerationFunction; - ColorReadFunction colorReadFunction; - - FastCopyFunctionMap fastCopyFunctions; - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; + angle::Format::ID formatID; }; + const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); struct VertexFormat diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp index 8622dc4d13..fd451a6e51 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -17,7 +17,9 @@ #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 "platform/Platform.h" +#include "platform/WorkaroundsD3D.h" #include "third_party/systeminfo/SystemInfo.h" @@ -133,21 +135,22 @@ D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) return d3dWrap; } -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +D3DCULL ConvertCullMode(gl::CullFaceMode 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(); + case gl::CullFaceMode::Front: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case gl::CullFaceMode::Back: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case gl::CullFaceMode::FrontAndBack: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: + UNREACHABLE(); } return cull; @@ -264,6 +267,21 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT } } +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; @@ -291,8 +309,8 @@ GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) { - GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat; - GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format; + GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).info().glInternalFormat; + GLenum convertedFormat = gl::GetSizedInternalFormatInfo(internalFormat).format; return convertedFormat == format; } @@ -302,7 +320,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3 gl::TextureCaps textureCaps; const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat); if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN) { @@ -333,7 +351,8 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3 { D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); - HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); + HRESULT result = d3d9->CheckDeviceMultiSampleType( + adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, nullptr); if (SUCCEEDED(result)) { textureCaps.sampleCounts.insert(i); @@ -364,18 +383,17 @@ void GenerateCaps(IDirect3D9 *d3d9, 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) + for (GLenum internalFormat : gl::GetAllSizedInternalFormats()) { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, - currentDisplayMode.Format); - textureCapsMap->insert(*internalFormat, textureCaps); + 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) + if (gl::GetSizedInternalFormatInfo(internalFormat).compressed) { - caps->compressedTextureFormats.push_back(*internalFormat); + caps->compressedTextureFormats.push_back(internalFormat); } } @@ -444,6 +462,8 @@ void GenerateCaps(IDirect3D9 *d3d9, // Vertex shader limits caps->maxVertexAttributes = 16; + // Vertex Attrib Binding not supported. + caps->maxVertexAttribBindings = caps->maxVertexAttributes; const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; caps->maxVertexUniformVectors = @@ -525,12 +545,12 @@ void GenerateCaps(IDirect3D9 *d3d9, { // 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() && adapterId.VendorId == VENDOR_ID_AMD); + !(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 (adapterId.VendorId == VENDOR_ID_AMD) + if (IsAMD(adapterId.VendorId)) { extensions->depthTextures = false; } @@ -548,18 +568,21 @@ void GenerateCaps(IDirect3D9 *d3d9, extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy); // Check occlusion query support by trying to create one - IDirect3DQuery9 *occlusionQuery = NULL; + IDirect3DQuery9 *occlusionQuery = nullptr; extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; SafeRelease(occlusionQuery); // Check event query support by trying to create one - IDirect3DQuery9 *eventQuery = NULL; + IDirect3DQuery9 *eventQuery = nullptr; extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; SafeRelease(eventQuery); - extensions->timerQuery = false; // Unimplemented extensions->disjointTimerQuery = false; extensions->robustness = true; + // It seems that only DirectX 10 and higher enforce the well-defined behavior of always + // returning zero values when out-of-bounds reads. See + // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_robustness.txt + extensions->robustBufferAccessBehavior = false; extensions->blendMinMax = true; extensions->framebufferBlit = true; extensions->framebufferMultisample = true; @@ -575,10 +598,11 @@ void GenerateCaps(IDirect3D9 *d3d9, extensions->colorBufferFloat = false; extensions->debugMarker = true; extensions->eglImage = true; + extensions->eglImageExternal = true; extensions->unpackSubimage = true; extensions->packSubimage = true; - extensions->vertexArrayObject = true; - extensions->noError = true; + extensions->syncQuery = extensions->fence; + extensions->copyTexture = true; // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil // state. @@ -625,15 +649,23 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize *levelOffset = upsampleCount; } -WorkaroundsD3D GenerateWorkarounds() +angle::WorkaroundsD3D GenerateWorkarounds() { - WorkaroundsD3D workarounds; + angle::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; + + // Call platform hooks for testing overrides. + auto *platform = ANGLEPlatformCurrent(); + platform->overrideWorkaroundsD3D(platform, &workarounds); + return workarounds; } -} +} // namespace d3d9 -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h index aa494adb62..5b65b8910a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h @@ -10,9 +10,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ #define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ -#include "libANGLE/angletypes.h" +#include "common/Color.h" #include "libANGLE/Caps.h" #include "libANGLE/Error.h" +#include "platform/WorkaroundsD3D.h" namespace gl { @@ -22,7 +23,6 @@ class FramebufferAttachment; namespace rx { class RenderTarget9; -struct WorkaroundsD3D; namespace gl_d3d9 { @@ -33,12 +33,13 @@ D3DBLEND ConvertBlendFunc(GLenum blend); D3DBLENDOP ConvertBlendOp(GLenum blendOp); D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCULL ConvertCullMode(gl::CullFaceMode 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); @@ -86,9 +87,9 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -WorkaroundsD3D GenerateWorkarounds(); +angle::WorkaroundsD3D GenerateWorkarounds(); } -} +} // namespace d3d9 #endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps index dc357d0fa6..ecc593cc78 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps @@ -24,6 +24,23 @@ float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; }; +float4 luminancepremultps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 luma = tex2D(tex, texcoord.xy).xxxw; + luma.rgb *= luma.a; + return luma * mult + add; +}; + +float4 luminanceunmultps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 luma = tex2D(tex, texcoord.xy).xxxw; + if (luma.a > 0.0f) + { + luma.rgb /= luma.a; + } + return luma * mult + add; +}; + // 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 @@ -31,3 +48,20 @@ float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR { return tex2D(tex, texcoord.xy) * mult + add; }; + +float4 componentmaskpremultps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 color = tex2D(tex, texcoord.xy); + color.rgb *= color.a; + return color * mult + add; +}; + +float4 componentmaskunmultps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 color = tex2D(tex, texcoord.xy); + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return color * mult + add; +}; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs index 3a36980b93..c68395a69c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs @@ -11,6 +11,7 @@ struct VS_OUTPUT }; uniform float4 halfPixelSize : c0; +uniform float4 texcoordOffset : c1; // Standard Vertex Shader // Input 0 is the homogenous position. @@ -22,22 +23,7 @@ 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); + Out.texcoord = ((position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0)) * float4(texcoordOffset.zw, 1.0, 1.0)) + float4(texcoordOffset.xy, 0, 0); return Out; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp deleted file mode 100644 index e1c955eb06..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils9.cpp: Queries for GL image formats and their translations to D3D -// formats. - -#include "libANGLE/renderer/d3d/formatutilsD3D.h" - -#include <map> - -#include "common/debug.h" -#include "libANGLE/renderer/d3d/imageformats.h" -#include "libANGLE/renderer/d3d/copyimage.h" - -namespace rx -{ - -typedef std::pair<GLenum, GLenum> FormatTypePair; -typedef std::pair<FormatTypePair, ColorWriteFunction> FormatWriteFunctionPair; -typedef std::map<FormatTypePair, ColorWriteFunction> FormatWriteFunctionMap; - -static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map, GLenum format, GLenum type, - ColorWriteFunction writeFunc) -{ - map->insert(FormatWriteFunctionPair(FormatTypePair(format, type), writeFunc)); -} - -static FormatWriteFunctionMap BuildFormatWriteFunctionMap() -{ - FormatWriteFunctionMap map; - - // | Format | Type | Color write function | - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>); - InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>); - - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> ); - - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> ); - - InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> ); - - InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> ); - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> ); - InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> ); - - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<A4R4G4B4, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<A1R5G5B5, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> ); - InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> ); - - InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL ); - - InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL ); - - InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL ); - - InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL ); - InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL ); - - return map; -} - -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type) -{ - static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap(); - FormatWriteFunctionMap::const_iterator iter = formatTypeMap.find(FormatTypePair(format, type)); - ASSERT(iter != formatTypeMap.end()); - if (iter != formatTypeMap.end()) - { - return iter->second; - } - else - { - return NULL; - } -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h index 6dd59ca94b..a245a0432f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h @@ -15,24 +15,15 @@ #include <cstddef> #include <stdint.h> -namespace rx -{ - -typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); +#include <map> -typedef void (*LoadImageFunction)(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); - -typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); +namespace gl +{ +struct FormatType; +} +namespace rx +{ typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); enum VertexConversionType @@ -42,9 +33,6 @@ enum VertexConversionType VERTEX_CONVERT_GPU = 2, VERTEX_CONVERT_BOTH = 3 }; - -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type); - -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h deleted file mode 100644 index 398ef26b30..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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. -// - -// generatemip.h: Defines the GenerateMip function, templated on the format -// type of the image for which mip levels are being generated. - -#ifndef LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ -#define LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ - -#include "libANGLE/renderer/d3d/imageformats.h" -#include "libANGLE/angletypes.h" - -namespace rx -{ - -template <typename T> -inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -} - -#include "generatemip.inl" - -#endif // LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl deleted file mode 100644 index 265783641e..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl +++ /dev/null @@ -1,266 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// generatemip.inl: Defines the GenerateMip function, templated on the format -// type of the image for which mip levels are being generated. - -#include "common/mathutil.h" - -namespace rx -{ - -namespace priv -{ - -template <typename T> -static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template <typename T> -static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template <typename T> -static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (size_t y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template <typename T> -static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth == 1); - - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template <typename T> -static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template <typename T> -static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (size_t y = 0; y < destHeight; y++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template <typename T> -static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template <typename T> -static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template <typename T> -static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t y = 0; y < destHeight; y++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(&tmp2, src4, src5); - T::average(&tmp3, src6, src7); - - T::average(&tmp4, &tmp0, &tmp1); - T::average(&tmp5, &tmp2, &tmp3); - - T::average(dst, &tmp4, &tmp5); - } - } - } -} - - -typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -template <typename T> -static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) -{ - uint8_t index = ((sourceWidth > 1) ? 1 : 0) | - ((sourceHeight > 1) ? 2 : 0) | - ((sourceDepth > 1) ? 4 : 0); - - switch (index) - { - case 0: return NULL; - case 1: return GenerateMip_X<T>; // W x 1 x 1 - case 2: return GenerateMip_Y<T>; // 1 x H x 1 - case 3: return GenerateMip_XY<T>; // W x H x 1 - case 4: return GenerateMip_Z<T>; // 1 x 1 x D - case 5: return GenerateMip_XZ<T>; // W x 1 x D - case 6: return GenerateMip_YZ<T>; // 1 x H x D - case 7: return GenerateMip_XYZ<T>; // W x H x D - } - - UNREACHABLE(); - return NULL; -} - -} - -template <typename T> -inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1); - size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1); - size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1); - - priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth); - ASSERT(generationFunction != NULL); - - generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, - mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h deleted file mode 100644 index 76f1830e64..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h +++ /dev/null @@ -1,1999 +0,0 @@ -// -// 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. -// - -// imageformats.h: Defines image format types with functions for mip generation -// and copying. - -#ifndef LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ -#define LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ - -#include "libANGLE/angletypes.h" - -#include "common/mathutil.h" - -namespace rx -{ - -// Several structures share functionality for reading, writing or mipmapping but the layout -// must match the texture format which the structure represents. If collapsing or typedefing -// structs in this header, make sure the functionality and memory layout is exactly the same. - -struct L8 -{ - unsigned char L; - - static void readColor(gl::ColorF *dst, const L8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = 1.0f; - } - - static void writeColor(L8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); - } - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = gl::average(src1->L, src2->L); - } -}; - -struct R8 -{ - unsigned char R; - - static void readColor(gl::ColorF *dst, const R8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - } - - static void writeColor(R8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - } - - static void average(R8 *dst, const R8 *src1, const R8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct A8 -{ - unsigned char A; - - static void readColor(gl::ColorF *dst, const A8 *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(A8 *dst, const gl::ColorF *src) - { - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void average(A8 *dst, const A8 *src1, const A8 *src2) - { - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct L8A8 -{ - unsigned char L; - unsigned char A; - - static void readColor(gl::ColorF *dst, const L8A8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(L8A8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct A8L8 -{ - unsigned char A; - unsigned char L; - - static void readColor(gl::ColorF *dst, const A8L8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(A8L8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct R8G8 -{ - unsigned char R; - unsigned char G; - - static void readColor(gl::ColorF *dst, const R8G8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8G8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8G8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - } - - static void writeColor(R8G8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - } - - static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct R8G8B8 -{ - unsigned char R; - unsigned char G; - unsigned char B; - - static void readColor(gl::ColorF *dst, const R8G8B8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8G8B8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->G; - dst->alpha = 1; - } - - static void writeColor(R8G8B8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - } - - static void writeColor(R8G8B8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - } - - static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct B8G8R8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - - static void readColor(gl::ColorF *dst, const B8G8R8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const B8G8R8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->G; - dst->alpha = 1; - } - - static void writeColor(B8G8R8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - } - - static void writeColor(B8G8R8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - } - - static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R5G6B5 -{ - // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant - // bits of the bitfield, and successive component occupying progressively less significant locations" - unsigned short RGB; - - static void readColor(gl::ColorF *dst, const R5G6B5 *src) - { - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB)); - dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB)); - dst->alpha = 1.0f; - } - - static void writeColor(R5G6B5 *dst, const gl::ColorF *src) - { - dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | - gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); - } - - static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) - { - dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) | - gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB))); - } -}; - -struct A8R8G8B8 -{ - unsigned char A; - unsigned char R; - unsigned char G; - unsigned char B; - - static void readColor(gl::ColorF *dst, const A8R8G8B8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - dst->A = static_cast<unsigned char>(src->alpha); - } - - static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct R8G8B8A8 -{ - unsigned char R; - unsigned char G; - unsigned char B; - unsigned char A; - - static void readColor(gl::ColorF *dst, const R8G8B8A8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - dst->A = static_cast<unsigned char>(src->alpha); - } - - static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct B8G8R8A8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void readColor(gl::ColorF *dst, const B8G8R8A8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - dst->A = gl::floatToNormalized<unsigned char>(src->alpha); - } - - static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - dst->A = static_cast<unsigned char>(src->alpha); - } - - static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct B8G8R8X8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char X; - - static void readColor(gl::ColorF *dst, const B8G8R8X8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned char>(src->red); - dst->G = gl::floatToNormalized<unsigned char>(src->green); - dst->B = gl::floatToNormalized<unsigned char>(src->blue); - dst->X = 255; - } - - static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned char>(src->red); - dst->G = static_cast<unsigned char>(src->green); - dst->B = static_cast<unsigned char>(src->blue); - dst->X = 255; - } - - static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - dst->X = 255; - } -}; - -struct A1R5G5B5 -{ - unsigned short ARGB; - - static void readColor(gl::ColorF *dst, const A1R5G5B5 *src) - { - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->ARGB)); - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->ARGB)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->ARGB)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->ARGB)); - } - - static void writeColor(A1R5G5B5 *dst, const gl::ColorF *src) - { - dst->ARGB = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | - gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | - gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); - } - - static void average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2) - { - dst->ARGB = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->ARGB), gl::getShiftedData<1, 15>(src2->ARGB))) | - gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->ARGB), gl::getShiftedData<5, 10>(src2->ARGB))) | - gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->ARGB), gl::getShiftedData<5, 5>(src2->ARGB))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->ARGB), gl::getShiftedData<5, 0>(src2->ARGB))); - } -}; - -struct R5G5B5A1 -{ - // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant - // bits of the bitfield, and successive component occupying progressively less significant locations" - unsigned short RGBA; - - static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) - { - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGBA)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 6>(src->RGBA)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 1>(src->RGBA)); - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 0>(src->RGBA)); - } - - static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) - { - dst->RGBA = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | - gl::shiftData<5, 6>(gl::floatToNormalized<5, unsigned short>(src->green)) | - gl::shiftData<5, 1>(gl::floatToNormalized<5, unsigned short>(src->blue)) | - gl::shiftData<1, 0>(gl::floatToNormalized<1, unsigned short>(src->alpha)); - } - - static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) - { - dst->RGBA = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGBA), gl::getShiftedData<5, 11>(src2->RGBA))) | - gl::shiftData<5, 6>(gl::average(gl::getShiftedData<5, 6>(src1->RGBA), gl::getShiftedData<5, 6>(src2->RGBA))) | - gl::shiftData<5, 1>(gl::average(gl::getShiftedData<5, 1>(src1->RGBA), gl::getShiftedData<5, 1>(src2->RGBA))) | - gl::shiftData<1, 0>(gl::average(gl::getShiftedData<1, 0>(src1->RGBA), gl::getShiftedData<1, 0>(src2->RGBA))); - } -}; - -struct R4G4B4A4 -{ - // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant - // bits of the bitfield, and successive component occupying progressively less significant locations" - unsigned short RGBA; - - static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) - { - dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->RGBA)); - dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->RGBA)); - dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->RGBA)); - dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->RGBA)); - } - - static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) - { - dst->RGBA = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->red)) | - gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->green)) | - gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->blue)) | - gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->alpha)); - } - - static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) - { - dst->RGBA = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->RGBA), gl::getShiftedData<4, 12>(src2->RGBA))) | - gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->RGBA), gl::getShiftedData<4, 8>(src2->RGBA))) | - gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->RGBA), gl::getShiftedData<4, 4>(src2->RGBA))) | - gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->RGBA), gl::getShiftedData<4, 0>(src2->RGBA))); - } -}; - -struct A4R4G4B4 -{ - unsigned short ARGB; - - static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) - { - dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->ARGB)); - dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->ARGB)); - dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->ARGB)); - dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->ARGB)); - } - - static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) - { - dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->alpha)) | - gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->red)) | - gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->green)) | - gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->blue)); - } - - static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) - { - dst->ARGB = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->ARGB), gl::getShiftedData<4, 12>(src2->ARGB))) | - gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->ARGB), gl::getShiftedData<4, 8>(src2->ARGB))) | - gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->ARGB), gl::getShiftedData<4, 4>(src2->ARGB))) | - gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->ARGB), gl::getShiftedData<4, 0>(src2->ARGB))); - } -}; - -struct R16 -{ - unsigned short R; - - static void readColor(gl::ColorF *dst, const R16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned short>(src->red); - } - - static void writeColor(R16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned short>(src->red); - } - - static void average(R16 *dst, const R16 *src1, const R16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R16G16 -{ - unsigned short R; - unsigned short G; - - static void readColor(gl::ColorF *dst, const R16G16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16G16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16G16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned short>(src->red); - dst->G = gl::floatToNormalized<unsigned short>(src->green); - } - - static void writeColor(R16G16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned short>(src->red); - dst->G = static_cast<unsigned short>(src->green); - } - - static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R16G16B16 -{ - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const R16G16B16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16G16B16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R16G16B16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned short>(src->red); - dst->G = gl::floatToNormalized<unsigned short>(src->green); - dst->B = gl::floatToNormalized<unsigned short>(src->blue); - } - - static void writeColor(R16G16B16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned short>(src->red); - dst->G = static_cast<unsigned short>(src->green); - dst->B = static_cast<unsigned short>(src->blue); - } - - static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R16G16B16A16 -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned short>(src->red); - dst->G = gl::floatToNormalized<unsigned short>(src->green); - dst->B = gl::floatToNormalized<unsigned short>(src->blue); - dst->A = gl::floatToNormalized<unsigned short>(src->alpha); - } - - static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned short>(src->red); - dst->G = static_cast<unsigned short>(src->green); - dst->B = static_cast<unsigned short>(src->blue); - dst->A = static_cast<unsigned short>(src->alpha); - } - - static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32 -{ - unsigned int R; - - static void readColor(gl::ColorF *dst, const R32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned int>(src->red); - } - - static void writeColor(R32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned int>(src->red); - } - - static void average(R32 *dst, const R32 *src1, const R32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R32G32 -{ - unsigned int R; - unsigned int G; - - static void readColor(gl::ColorF *dst, const R32G32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32G32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32G32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned int>(src->red); - dst->G = gl::floatToNormalized<unsigned int>(src->green); - } - - static void writeColor(R32G32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned int>(src->red); - dst->G = static_cast<unsigned int>(src->green); - } - - static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32 -{ - unsigned int R; - unsigned int G; - unsigned int B; - - static void readColor(gl::ColorF *dst, const R32G32B32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32G32B32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R32G32B32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned int>(src->red); - dst->G = gl::floatToNormalized<unsigned int>(src->green); - dst->B = gl::floatToNormalized<unsigned int>(src->blue); - } - - static void writeColor(R32G32B32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned int>(src->red); - dst->G = static_cast<unsigned int>(src->green); - dst->B = static_cast<unsigned int>(src->blue); - } - - static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R32G32B32A32 -{ - unsigned int R; - unsigned int G; - unsigned int B; - unsigned int A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<unsigned int>(src->red); - dst->G = gl::floatToNormalized<unsigned int>(src->green); - dst->B = gl::floatToNormalized<unsigned int>(src->blue); - dst->A = gl::floatToNormalized<unsigned int>(src->alpha); - } - - static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned int>(src->red); - dst->G = static_cast<unsigned int>(src->green); - dst->B = static_cast<unsigned int>(src->blue); - dst->A = static_cast<unsigned int>(src->alpha); - } - - static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R8S -{ - char R; - - static void readColor(gl::ColorF *dst, const R8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<char>(src->red); - } - - static void writeColor(R8S *dst, const gl::ColorI *src) - { - dst->R = static_cast<char>(src->red); - } - - static void average(R8S *dst, const R8S *src1, const R8S *src2) - { - dst->R = static_cast<char>(gl::average(src1->R, src2->R)); - } -}; - -struct R8G8S -{ - char R; - char G; - - static void readColor(gl::ColorF *dst, const R8G8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8G8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8G8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<char>(src->red); - dst->G = gl::floatToNormalized<char>(src->green); - } - - static void writeColor(R8G8S *dst, const gl::ColorI *src) - { - dst->R = static_cast<char>(src->red); - dst->G = static_cast<char>(src->green); - } - - static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) - { - dst->R = static_cast<char>(gl::average(src1->R, src2->R)); - dst->G = static_cast<char>(gl::average(src1->G, src2->G)); - } -}; - -struct R8G8B8S -{ - char R; - char G; - char B; - - static void readColor(gl::ColorF *dst, const R8G8B8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8G8B8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R8G8B8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<char>(src->red); - dst->G = gl::floatToNormalized<char>(src->green); - dst->B = gl::floatToNormalized<char>(src->blue); - } - - static void writeColor(R8G8B8S *dst, const gl::ColorI *src) - { - dst->R = static_cast<char>(src->red); - dst->G = static_cast<char>(src->green); - dst->B = static_cast<char>(src->blue); - } - - static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) - { - dst->R = static_cast<char>(gl::average(src1->R, src2->R)); - dst->G = static_cast<char>(gl::average(src1->G, src2->G)); - dst->B = static_cast<char>(gl::average(src1->B, src2->B)); - } -}; - -struct R8G8B8A8S -{ - char R; - char G; - char B; - char A; - - static void readColor(gl::ColorF *dst, const R8G8B8A8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R8G8B8A8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<char>(src->red); - dst->G = gl::floatToNormalized<char>(src->green); - dst->B = gl::floatToNormalized<char>(src->blue); - dst->A = gl::floatToNormalized<char>(src->alpha); - } - - static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src) - { - dst->R = static_cast<char>(src->red); - dst->G = static_cast<char>(src->green); - dst->B = static_cast<char>(src->blue); - dst->A = static_cast<char>(src->alpha); - } - - static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) - { - dst->R = static_cast<char>(gl::average(src1->R, src2->R)); - dst->G = static_cast<char>(gl::average(src1->G, src2->G)); - dst->B = static_cast<char>(gl::average(src1->B, src2->B)); - dst->A = static_cast<char>(gl::average(src1->A, src2->A)); - } -}; - -struct R16S -{ - short R; - - static void readColor(gl::ColorF *dst, const R16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<short>(src->red); - } - - static void writeColor(R16S *dst, const gl::ColorI *src) - { - dst->R = static_cast<short>(src->red); - } - - static void average(R16S *dst, const R16S *src1, const R16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R16G16S -{ - short R; - short G; - - static void readColor(gl::ColorF *dst, const R16G16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16G16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16G16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<short>(src->red); - dst->G = gl::floatToNormalized<short>(src->green); - } - - static void writeColor(R16G16S *dst, const gl::ColorI *src) - { - dst->R = static_cast<short>(src->red); - dst->G = static_cast<short>(src->green); - } - - static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R16G16B16S -{ - short R; - short G; - short B; - - static void readColor(gl::ColorF *dst, const R16G16B16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16G16B16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R16G16B16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<short>(src->red); - dst->G = gl::floatToNormalized<short>(src->green); - dst->B = gl::floatToNormalized<short>(src->blue); - } - - static void writeColor(R16G16B16S *dst, const gl::ColorI *src) - { - dst->R = static_cast<short>(src->red); - dst->G = static_cast<short>(src->green); - dst->B = static_cast<short>(src->blue); - } - - static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R16G16B16A16S -{ - short R; - short G; - short B; - short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R16G16B16A16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<short>(src->red); - dst->G = gl::floatToNormalized<short>(src->green); - dst->B = gl::floatToNormalized<short>(src->blue); - dst->A = gl::floatToNormalized<short>(src->alpha); - } - - static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src) - { - dst->R = static_cast<short>(src->red); - dst->G = static_cast<short>(src->green); - dst->B = static_cast<short>(src->blue); - dst->A = static_cast<short>(src->alpha); - } - - static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32S -{ - int R; - - static void readColor(gl::ColorF *dst, const R32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<int>(src->red); - } - - static void writeColor(R32S *dst, const gl::ColorI *src) - { - dst->R = static_cast<int>(src->red); - } - - static void average(R32S *dst, const R32S *src1, const R32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R32G32S -{ - int R; - int G; - - static void readColor(gl::ColorF *dst, const R32G32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32G32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32G32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<int>(src->red); - dst->G = gl::floatToNormalized<int>(src->green); - } - - static void writeColor(R32G32S *dst, const gl::ColorI *src) - { - dst->R = static_cast<int>(src->red); - dst->G = static_cast<int>(src->green); - } - - static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32S -{ - int R; - int G; - int B; - - static void readColor(gl::ColorF *dst, const R32G32B32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32G32B32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R32G32B32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<int>(src->red); - dst->G = gl::floatToNormalized<int>(src->green); - dst->B = gl::floatToNormalized<int>(src->blue); - } - - static void writeColor(R32G32B32S *dst, const gl::ColorI *src) - { - dst->R = static_cast<int>(src->red); - dst->G = static_cast<int>(src->green); - dst->B = static_cast<int>(src->blue); - } - - static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R32G32B32A32S -{ - int R; - int G; - int B; - int A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R32G32B32A32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<int>(src->red); - dst->G = gl::floatToNormalized<int>(src->green); - dst->B = gl::floatToNormalized<int>(src->blue); - dst->A = gl::floatToNormalized<int>(src->alpha); - } - - static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src) - { - dst->R = static_cast<int>(src->red); - dst->G = static_cast<int>(src->green); - dst->B = static_cast<int>(src->blue); - dst->A = static_cast<int>(src->alpha); - } - - static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct A16B16G16R16F -{ - unsigned short A; - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const A16B16G16R16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16G16B16A16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16F -{ - unsigned short R; - - static void readColor(gl::ColorF *dst, const R16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - } - - static void average(R16F *dst, const R16F *src1, const R16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - } -}; - -struct A16F -{ - unsigned short A; - - static void readColor(gl::ColorF *dst, const A16F *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(A16F *dst, const gl::ColorF *src) - { - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(A16F *dst, const A16F *src1, const A16F *src2) - { - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct L16F -{ - unsigned short L; - - static void readColor(gl::ColorF *dst, const L16F *src) - { - float lum = gl::float16ToFloat32(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = 1.0f; - } - - static void writeColor(L16F *dst, const gl::ColorF *src) - { - dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); - } - - static void average(L16F *dst, const L16F *src1, const L16F *src2) - { - dst->L = gl::averageHalfFloat(src1->L, src2->L); - } -}; - -struct L16A16F -{ - unsigned short L; - unsigned short A; - - static void readColor(gl::ColorF *dst, const L16A16F *src) - { - float lum = gl::float16ToFloat32(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(L16A16F *dst, const gl::ColorF *src) - { - dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2) - { - dst->L = gl::averageHalfFloat(src1->L, src2->L); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16G16F -{ - unsigned short R; - unsigned short G; - - static void readColor(gl::ColorF *dst, const R16G16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R16G16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - } - - static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - } -}; - -struct R16G16B16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const R16G16B16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = 1.0f; - } - - static void writeColor(R16G16B16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - } - - static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - } -}; - -struct A32B32G32R32F -{ - float A; - float R; - float G; - float B; - - static void readColor(gl::ColorF *dst, const A32B32G32R32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - dst->A = src->alpha; - } - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32G32B32A32F -{ - float R; - float G; - float B; - float A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - dst->A = src->alpha; - } - - static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32F -{ - float R; - - static void readColor(gl::ColorF *dst, const R32F *src) - { - dst->red = src->R; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - } - - static void average(R32F *dst, const R32F *src1, const R32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct A32F -{ - float A; - - static void readColor(gl::ColorF *dst, const A32F *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = src->A; - } - - static void writeColor(A32F *dst, const gl::ColorF *src) - { - dst->A = src->alpha; - } - - static void average(A32F *dst, const A32F *src1, const A32F *src2) - { - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct L32F -{ - float L; - - static void readColor(gl::ColorF *dst, const L32F *src) - { - dst->red = src->L; - dst->green = src->L; - dst->blue = src->L; - dst->alpha = 1.0f; - } - - static void writeColor(L32F *dst, const gl::ColorF *src) - { - dst->L = (src->red + src->green + src->blue) / 3.0f; - } - - static void average(L32F *dst, const L32F *src1, const L32F *src2) - { - dst->L = gl::average(src1->L, src2->L); - } -}; - -struct L32A32F -{ - float L; - float A; - - static void readColor(gl::ColorF *dst, const L32A32F *src) - { - dst->red = src->L; - dst->green = src->L; - dst->blue = src->L; - dst->alpha = src->A; - } - - static void writeColor(L32A32F *dst, const gl::ColorF *src) - { - dst->L = (src->red + src->green + src->blue) / 3.0f; - dst->A = src->alpha; - } - - static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2) - { - dst->L = gl::average(src1->L, src2->L); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32G32F -{ - float R; - float G; - - static void readColor(gl::ColorF *dst, const R32G32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R32G32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - } - - static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32F -{ - float R; - float G; - float B; - - static void readColor(gl::ColorF *dst, const R32G32B32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1.0f; - } - - static void writeColor(R32G32B32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - } - - static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R10G10B10A2 -{ - unsigned int R : 10; - unsigned int G : 10; - unsigned int B : 10; - unsigned int A : 2; - - static void readColor(gl::ColorF *dst, const R10G10B10A2 *src) - { - dst->red = gl::normalizedToFloat<10>(src->R); - dst->green = gl::normalizedToFloat<10>(src->G); - dst->blue = gl::normalizedToFloat<10>(src->B); - dst->alpha = gl::normalizedToFloat< 2>(src->A); - } - - static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<10, unsigned int>(src->red); - dst->G = gl::floatToNormalized<10, unsigned int>(src->green); - dst->B = gl::floatToNormalized<10, unsigned int>(src->blue); - dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha); - } - - static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src) - { - dst->R = static_cast<unsigned int>(src->red); - dst->G = static_cast<unsigned int>(src->green); - dst->B = static_cast<unsigned int>(src->blue); - dst->A = static_cast<unsigned int>(src->alpha); - } - - static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R9G9B9E5 -{ - unsigned int R : 9; - unsigned int G : 9; - unsigned int B : 9; - unsigned int E : 5; - - static void readColor(gl::ColorF *dst, const R9G9B9E5 *src) - { - gl::convert999E5toRGBFloats(gl::bitCast<unsigned int>(*src), &dst->red, &dst->green, &dst->blue); - dst->alpha = 1.0f; - } - - static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src) - { - *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(src->red, - src->green, - src->blue); - } - - static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2) - { - float r1, g1, b1; - gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src1), &r1, &g1, &b1); - - float r2, g2, b2; - gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src2), &r2, &g2, &b2); - - *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2), - gl::average(g1, g2), - gl::average(b1, b2)); - } -}; - -struct R11G11B10F -{ - unsigned int R : 11; - unsigned int G : 11; - unsigned int B : 10; - - static void readColor(gl::ColorF *dst, const R11G11B10F *src) - { - dst->red = gl::float11ToFloat32(src->R); - dst->green = gl::float11ToFloat32(src->G); - dst->blue = gl::float10ToFloat32(src->B); - dst->alpha = 1.0f; - } - - static void writeColor(R11G11B10F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat11(src->red); - dst->G = gl::float32ToFloat11(src->green); - dst->B = gl::float32ToFloat10(src->blue); - } - - static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2) - { - dst->R = gl::averageFloat11(src1->R, src2->R); - dst->G = gl::averageFloat11(src1->G, src2->G); - dst->B = gl::averageFloat10(src1->B, src2->B); - } -}; - -} - -#endif // LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp deleted file mode 100644 index b9b9e5e4ab..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp +++ /dev/null @@ -1,697 +0,0 @@ -// -// 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. -// - -// loadimage.cpp: Defines image loading functions. - -#include "libANGLE/renderer/d3d/loadimage.h" - -namespace rx -{ - -void LoadA8ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = static_cast<uint32_t>(source[x]) << 24; - } - } - } -} - -void LoadA8ToBGRA8(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) -{ - // Same as loading to RGBA - LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadA32FToRGBA32F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0.0f; - dest[4 * x + 1] = 0.0f; - dest[4 * x + 2] = 0.0f; - dest[4 * x + 3] = source[x]; - } - } - } -} - -void LoadA16FToRGBA16F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } - } -} - -void LoadL8ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint8_t sourceVal = source[x]; - dest[4 * x + 0] = sourceVal; - dest[4 * x + 1] = sourceVal; - dest[4 * x + 2] = sourceVal; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadL8ToBGRA8(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) -{ - // Same as loading to RGBA - LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadL32FToRGBA32F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 1.0f; - } - } - } -} - -void LoadL16FToRGBA16F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = gl::Float16One; - } - } - } -} - -void LoadLA8ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2 * x + 0]; - dest[4 * x + 1] = source[2 * x + 0]; - dest[4 * x + 2] = source[2 * x + 0]; - dest[4 * x + 3] = source[2 * x + 1]; - } - } - } -} - -void LoadLA8ToBGRA8(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) -{ - // Same as loading to RGBA - LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadLA32FToRGBA32F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2 * x + 0]; - dest[4 * x + 1] = source[2 * x + 0]; - dest[4 * x + 2] = source[2 * x + 0]; - dest[4 * x + 3] = source[2 * x + 1]; - } - } - } -} - -void LoadLA16FToRGBA16F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2 * x + 0]; - dest[4 * x + 1] = source[2 * x + 0]; - dest[4 * x + 2] = source[2 * x + 0]; - dest[4 * x + 3] = source[2 * x + 1]; - } - } - } -} - -void LoadRGB8ToBGRX8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 2]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 0]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadRG8ToBGRX8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0x00; - dest[4 * x + 1] = source[x * 2 + 1]; - dest[4 * x + 2] = source[x * 2 + 0]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR8ToBGRX8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0x00; - dest[4 * x + 1] = 0x00; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR5G6B5ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgb = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13)); - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR5G6B5ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgb = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2)); - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadRGBA8ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t rgba = source[x]; - dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } - } -} - -void LoadRGBA4ToARGB4(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = ANGLE_ROTR16(source[x], 4); - } - } - } -} - -void LoadRGBA4ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgba = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12)); - dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0)); - } - } - } -} - -void LoadRGBA4ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgba = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4)); - dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0)); - } - } - } -} - -void LoadBGRA4ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t bgra = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12)); - dest[4 * x + 1] = static_cast<uint8_t>(((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4)); - dest[4 * x + 3] = static_cast<uint8_t>(((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0)); - } - } - } -} - -void LoadRGB5A1ToA1RGB5(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = ANGLE_ROTR16(source[x], 1); - } - } - } -} - -void LoadRGB5A1ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgba = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13)); - dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0); - } - } - } -} - -void LoadRGB5A1ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgba = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13)); - dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3)); - dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0); - } - } - } -} - -void LoadBGR5A1ToBGRA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t bgra = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>(((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13)); - dest[4 * x + 1] = static_cast<uint8_t>(((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8)); - dest[4 * x + 2] = static_cast<uint8_t>(((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3)); - dest[4 * x + 3] = static_cast<uint8_t>((bgra & 0x0001) ? 0xFF : 0); - } - } - } -} - -void LoadRGB10A2ToRGBA8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t rgba = source[x]; - dest[4 * x + 0] = static_cast<uint8_t>((rgba & 0x000003FF) >> 2); - dest[4 * x + 1] = static_cast<uint8_t>((rgba & 0x000FFC00) >> 12); - dest[4 * x + 2] = static_cast<uint8_t>((rgba & 0x3FF00000) >> 22); - dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0xC0000000) >> 30) * 0x55); - } - } - } -} - -void LoadRGB16FToRGB9E5(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), - gl::float16ToFloat32(source[x * 3 + 1]), - gl::float16ToFloat32(source[x * 3 + 2])); - } - } - } -} - -void LoadRGB32FToRGB9E5(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); - } - } - } -} - -void LoadRGB16FToRG11B10F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | - (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | - (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22); - } - } - } -} - -void LoadRGB32FToRG11B10F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | - (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | - (gl::float32ToFloat10(source[x * 3 + 2]) << 22); - } - } - } -} - -void LoadG8R24ToR24G8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t d = source[x] >> 8; - uint8_t s = source[x] & 0xFF; - dest[x] = d | (s << 24); - } - } - } -} - -void LoadRGB32FToRGBA16F(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); - dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); - dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]); - dest[x * 4 + 3] = gl::Float16One; - } - } - } -} - -void LoadR32ToR16(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = source[x] >> 16; - } - } - } -} - -void LoadR32ToR24G8(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) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x++) - { - dest[x] = source[x] >> 8; - } - } - } -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h deleted file mode 100644 index 6c5118365e..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h +++ /dev/null @@ -1,201 +0,0 @@ -// -// 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. -// - -// loadimage.h: Defines image loading functions - -#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ -#define LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ - -#include "libANGLE/angletypes.h" - -#include <stdint.h> - -namespace rx -{ - -void LoadA8ToRGBA8(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); - -void LoadA8ToBGRA8(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); - -void LoadA8ToBGRA8_SSE2(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); - -void LoadA32FToRGBA32F(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); - -void LoadA16FToRGBA16F(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); - -void LoadL8ToRGBA8(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); - -void LoadL8ToBGRA8(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); - -void LoadL32FToRGBA32F(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); - -void LoadL16FToRGBA16F(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); - -void LoadLA8ToRGBA8(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); - -void LoadLA8ToBGRA8(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); - -void LoadLA32FToRGBA32F(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); - -void LoadLA16FToRGBA16F(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); - -void LoadRGB8ToBGRX8(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); - -void LoadRG8ToBGRX8(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); - -void LoadR8ToBGRX8(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); - -void LoadR5G6B5ToBGRA8(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); - -void LoadR5G6B5ToRGBA8(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); - -void LoadRGBA8ToBGRA8_SSE2(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); - -void LoadRGBA8ToBGRA8(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); - -void LoadRGBA4ToARGB4(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); - -void LoadRGBA4ToBGRA8(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); - -void LoadRGBA4ToRGBA8(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); - -void LoadBGRA4ToBGRA8(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); - -void LoadRGB5A1ToA1RGB5(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); - -void LoadRGB5A1ToBGRA8(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); - -void LoadRGB5A1ToRGBA8(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); - -void LoadBGR5A1ToBGRA8(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); - -void LoadRGB10A2ToRGBA8(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); - -void LoadRGB16FToRGB9E5(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); - -void LoadRGB32FToRGB9E5(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); - -void LoadRGB16FToRG11B10F(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); - -void LoadRGB32FToRG11B10F(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); - -void LoadG8R24ToR24G8(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); - -template <typename type, size_t componentCount> -inline void LoadToNative(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); - -template <typename type, uint32_t fourthComponentBits> -inline void LoadToNative3To4(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); - -template <size_t componentCount> -inline void Load32FTo16F(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); - -void LoadRGB32FToRGBA16F(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); - -template <size_t blockWidth, size_t blockHeight, size_t blockSize> -inline void LoadCompressedToNative(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); - -void LoadR32ToR16(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); - -template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> -inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR32ToR24G8(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); - -template <typename T> -inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); - -template <typename T> -inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); - -} - -#include "loadimage.inl" - -#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl deleted file mode 100644 index 920e667db1..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl +++ /dev/null @@ -1,156 +0,0 @@ -// -// 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. -// - -#include "common/mathutil.h" - -namespace rx -{ - -template <typename T> -inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch)); -} - -template <typename T> -inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch)); -} - -template <typename type, size_t componentCount> -inline void LoadToNative(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) -{ - const size_t rowSize = width * sizeof(type) * componentCount; - const size_t layerSize = rowSize * height; - const size_t imageSize = layerSize * depth; - - if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) - { - ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); - memcpy(output, input, imageSize); - } - else if (rowSize == inputRowPitch && rowSize == outputRowPitch) - { - for (size_t z = 0; z < depth; z++) - { - const type *source = OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch); - - memcpy(dest, source, layerSize); - } - } - else - { - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * sizeof(type) * componentCount); - } - } - } -} - -template <typename type, uint32_t fourthComponentBits> -inline void LoadToNative3To4(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) -{ - const type fourthValue = gl::bitCast<type>(fourthComponentBits); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x * 4 + 0] = source[x * 3 + 0]; - dest[x * 4 + 1] = source[x * 3 + 1]; - dest[x * 4 + 2] = source[x * 3 + 2]; - dest[x * 4 + 3] = fourthValue; - } - } - } -} - -template <size_t componentCount> -inline void Load32FTo16F(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) -{ - const size_t elementWidth = componentCount * width; - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < elementWidth; x++) - { - dest[x] = gl::float32ToFloat16(source[x]); - } - } - } -} - -template <size_t blockWidth, size_t blockHeight, size_t blockSize> -inline void LoadCompressedToNative(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) -{ - const size_t columns = (width + (blockWidth - 1)) / blockWidth; - const size_t rows = (height + (blockHeight - 1)) / blockHeight; - - for (size_t z = 0; z < depth; ++z) - { - for (size_t y = 0; y < rows; ++y) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, columns * blockSize); - } - } -} - -template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> -inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - type writeValues[4] = - { - gl::bitCast<type>(firstBits), - gl::bitCast<type>(secondBits), - gl::bitCast<type>(thirdBits), - gl::bitCast<type>(fourthBits), - }; - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - type *destRow = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - type* destPixel = destRow + x * 4; - - // This could potentially be optimized by generating an entire row of initialization - // data and copying row by row instead of pixel by pixel. - memcpy(destPixel, writeValues, sizeof(type) * 4); - } - } - } -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp deleted file mode 100644 index c87d35c82b..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// 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. -// - -// loadimageSSE2.cpp: Defines image loading functions. It's -// in a separated file for GCC, which can enable SSE usage only per-file, -// not for code blocks that use SSE2 explicitly. - -#include "libANGLE/renderer/d3d/loadimage.h" - -#include "common/platform.h" - -#ifdef ANGLE_USE_SSE -#include <emmintrin.h> -#endif - -namespace rx -{ - -void LoadA8ToBGRA8_SSE2(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) -{ -#if defined(ANGLE_USE_SSE) - __m128i zeroWide = _mm_setzero_si128(); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - - size_t x = 0; - - // Make output writes aligned - for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++) - { - dest[x] = static_cast<uint32_t>(source[x]) << 24; - } - - for (; x + 7 < width; x += 8) - { - __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x])); - // Interleave each byte to 16bit, make the lower byte to zero - sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); - // Interleave each 16bit to 32bit, make the lower 16bit to zero - __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); - __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); - - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); - } - - // Handle the remainder - for (; x < width; x++) - { - dest[x] = static_cast<uint32_t>(source[x]) << 24; - } - } - } -#else - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#endif -} - -void LoadRGBA8ToBGRA8_SSE2(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) -{ -#if defined(ANGLE_USE_SSE) - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); - - size_t x = 0; - - // Make output writes aligned - for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++) - { - uint32_t rgba = source[x]; - dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - - for (; x + 3 < width; x += 4) - { - __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x])); - // Mask out g and a, which don't change - __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); - // Mask out b and r - __m128i brComponents = _mm_and_si128(sourceData, brMask); - // Swap b and r - __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); - __m128i result = _mm_or_si128(gaComponents, brSwapped); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); - } - - // Perform leftover writes - for (; x < width; x++) - { - uint32_t rgba = source[x]; - dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } - } -#else - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#endif -} - -} - diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp deleted file mode 100644 index 26a3b32ce0..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp +++ /dev/null @@ -1,1435 +0,0 @@ -// -// 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. -// - -// loadimage_etc.cpp: Decodes ETC and EAC encoded textures. - -#include "libANGLE/renderer/d3d/loadimage_etc.h" - -#include "libANGLE/renderer/d3d/loadimage.h" -#include "libANGLE/renderer/d3d/imageformats.h" - -namespace rx -{ -namespace -{ -// Table 3.17.2 sorted according to table 3.17.3 -// clang-format off -static const int intensityModifierDefault[][4] = -{ - { 2, 8, -2, -8 }, - { 5, 17, -5, -17 }, - { 9, 29, -9, -29 }, - { 13, 42, -13, -42 }, - { 18, 60, -18, -60 }, - { 24, 80, -24, -80 }, - { 33, 106, -33, -106 }, - { 47, 183, -47, -183 }, -}; -// clang-format on - -// Table C.12, intensity modifier for non opaque punchthrough alpha -// clang-format off -static const int intensityModifierNonOpaque[][4] = -{ - { 0, 8, 0, -8 }, - { 0, 17, 0, -17 }, - { 0, 29, 0, -29 }, - { 0, 42, 0, -42 }, - { 0, 60, 0, -60 }, - { 0, 80, 0, -80 }, - { 0, 106, 0, -106 }, - { 0, 183, 0, -183 }, -}; -// clang-format on - -// Table C.7, mapping from pixel index values to modifier value orders -// clang-format off -static const int valueMappingTable[] = -{ - 2, 3, 1, 0 -}; -// clang-format on - -struct ETC2Block -{ - // Decodes unsigned single or dual channel block to bytes - void decodeAsSingleChannel(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destPixelStride, - size_t destRowPitch, - bool isSigned) const - { - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - uint8_t *row = dest + (j * destRowPitch); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - uint8_t *pixel = row + (i * destPixelStride); - if (isSigned) - { - *pixel = clampSByte(getSingleChannel(i, j, isSigned)); - } - else - { - *pixel = clampByte(getSingleChannel(i, j, isSigned)); - } - } - } - } - - // Decodes RGB block to rgba8 - void decodeAsRGB(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - const uint8_t alphaValues[4][4], - bool punchThroughAlpha) const - { - bool opaqueBit = u.idht.mode.idm.diffbit; - bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit; - // Select mode - if (u.idht.mode.idm.diffbit || punchThroughAlpha) - { - const auto &block = u.idht.mode.idm.colors.diff; - int r = (block.R + block.dR); - int g = (block.G + block.dG); - int b = (block.B + block.dB); - if (r < 0 || r > 31) - { - decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues, - nonOpaquePunchThroughAlpha); - } - else if (g < 0 || g > 31) - { - decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues, - nonOpaquePunchThroughAlpha); - } - else if (b < 0 || b > 31) - { - decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues); - } - else - { - decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues, - nonOpaquePunchThroughAlpha); - } - } - else - { - decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues, - nonOpaquePunchThroughAlpha); - } - } - - // Transcodes RGB block to BC1 - void transcodeAsBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool punchThroughAlpha) const - { - bool opaqueBit = u.idht.mode.idm.diffbit; - bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit; - // Select mode - if (u.idht.mode.idm.diffbit || punchThroughAlpha) - { - const auto &block = u.idht.mode.idm.colors.diff; - int r = (block.R + block.dR); - int g = (block.G + block.dG); - int b = (block.B + block.dB); - if (r < 0 || r > 31) - { - transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha); - } - else if (g < 0 || g > 31) - { - transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha); - } - else if (b < 0 || b > 31) - { - transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues); - } - else - { - transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues, - nonOpaquePunchThroughAlpha); - } - } - else - { - transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues, - nonOpaquePunchThroughAlpha); - } - } - - private: - union - { - // Individual, differential, H and T modes - struct - { - union - { - // Individual and differential modes - struct - { - union - { - struct // Individual colors - { - unsigned char R2 : 4; - unsigned char R1 : 4; - unsigned char G2 : 4; - unsigned char G1 : 4; - unsigned char B2 : 4; - unsigned char B1 : 4; - } indiv; - struct // Differential colors - { - signed char dR : 3; - unsigned char R : 5; - signed char dG : 3; - unsigned char G : 5; - signed char dB : 3; - unsigned char B : 5; - } diff; - } colors; - bool flipbit : 1; - bool diffbit : 1; - unsigned char cw2 : 3; - unsigned char cw1 : 3; - } idm; - // T mode - struct - { - // Byte 1 - unsigned char TR1b : 2; - unsigned char TdummyB : 1; - unsigned char TR1a : 2; - unsigned char TdummyA : 3; - // Byte 2 - unsigned char TB1 : 4; - unsigned char TG1 : 4; - // Byte 3 - unsigned char TG2 : 4; - unsigned char TR2 : 4; - // Byte 4 - unsigned char Tdb : 1; - bool Tflipbit : 1; - unsigned char Tda : 2; - unsigned char TB2 : 4; - } tm; - // H mode - struct - { - // Byte 1 - unsigned char HG1a : 3; - unsigned char HR1 : 4; - unsigned char HdummyA : 1; - // Byte 2 - unsigned char HB1b : 2; - unsigned char HdummyC : 1; - unsigned char HB1a : 1; - unsigned char HG1b : 1; - unsigned char HdummyB : 3; - // Byte 3 - unsigned char HG2a : 3; - unsigned char HR2 : 4; - unsigned char HB1c : 1; - // Byte 4 - unsigned char Hdb : 1; - bool Hflipbit : 1; - unsigned char Hda : 1; - unsigned char HB2 : 4; - unsigned char HG2b : 1; - } hm; - } mode; - unsigned char pixelIndexMSB[2]; - unsigned char pixelIndexLSB[2]; - } idht; - // planar mode - struct - { - // Byte 1 - unsigned char GO1 : 1; - unsigned char RO : 6; - unsigned char PdummyA : 1; - // Byte 2 - unsigned char BO1 : 1; - unsigned char GO2 : 6; - unsigned char PdummyB : 1; - // Byte 3 - unsigned char BO3a : 2; - unsigned char PdummyD : 1; - unsigned char BO2 : 2; - unsigned char PdummyC : 3; - // Byte 4 - unsigned char RH2 : 1; - bool Pflipbit : 1; - unsigned char RH1 : 5; - unsigned char BO3b : 1; - // Byte 5 - unsigned char BHa : 1; - unsigned char GH : 7; - // Byte 6 - unsigned char RVa : 3; - unsigned char BHb : 5; - // Byte 7 - unsigned char GVa : 5; - unsigned char RVb : 3; - // Byte 8 - unsigned char BV : 6; - unsigned char GVb : 2; - } pblk; - // Single channel block - struct - { - union - { - unsigned char us; - signed char s; - } base_codeword; - unsigned char table_index : 4; - unsigned char multiplier : 4; - unsigned char mc1 : 2; - unsigned char mb : 3; - unsigned char ma : 3; - unsigned char mf1 : 1; - unsigned char me : 3; - unsigned char md : 3; - unsigned char mc2 : 1; - unsigned char mh : 3; - unsigned char mg : 3; - unsigned char mf2 : 2; - unsigned char mk1 : 2; - unsigned char mj : 3; - unsigned char mi : 3; - unsigned char mn1 : 1; - unsigned char mm : 3; - unsigned char ml : 3; - unsigned char mk2 : 1; - unsigned char mp : 3; - unsigned char mo : 3; - unsigned char mn2 : 2; - } scblk; - } u; - - static unsigned char clampByte(int value) - { - return static_cast<unsigned char>(gl::clamp(value, 0, 255)); - } - - static signed char clampSByte(int value) - { - return static_cast<signed char>(gl::clamp(value, -128, 127)); - } - - static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha) - { - R8G8B8A8 rgba; - rgba.R = clampByte(red); - rgba.G = clampByte(green); - rgba.B = clampByte(blue); - rgba.A = clampByte(alpha); - return rgba; - } - - static R8G8B8A8 createRGBA(int red, int green, int blue) - { - return createRGBA(red, green, blue, 255); - } - - static int extend_4to8bits(int x) { return (x << 4) | x; } - static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); } - static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); } - static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); } - - void decodeIndividualBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - const auto &block = u.idht.mode.idm.colors.indiv; - int r1 = extend_4to8bits(block.R1); - int g1 = extend_4to8bits(block.G1); - int b1 = extend_4to8bits(block.B1); - int r2 = extend_4to8bits(block.R2); - int g2 = extend_4to8bits(block.G2); - int b2 = extend_4to8bits(block.B2); - decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2, - alphaValues, nonOpaquePunchThroughAlpha); - } - - void decodeDifferentialBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - const auto &block = u.idht.mode.idm.colors.diff; - int b1 = extend_5to8bits(block.B); - int g1 = extend_5to8bits(block.G); - int r1 = extend_5to8bits(block.R); - int r2 = extend_5to8bits(block.R + block.dR); - int g2 = extend_5to8bits(block.G + block.dG); - int b2 = extend_5to8bits(block.B + block.dB); - decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2, - alphaValues, nonOpaquePunchThroughAlpha); - } - - void decodeIndividualOrDifferentialBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - int r1, - int g1, - int b1, - int r2, - int g2, - int b2, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - const auto intensityModifier = - nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; - - R8G8B8A8 subblockColors0[4]; - R8G8B8A8 subblockColors1[4]; - for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++) - { - const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx]; - subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1); - - const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx]; - subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2); - } - - if (u.idht.mode.idm.flipbit) - { - uint8_t *curPixel = dest; - for (size_t j = 0; j < 2 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - row[i] = subblockColors0[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - curPixel += destRowPitch; - } - for (size_t j = 2; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - row[i] = subblockColors1[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - curPixel += destRowPitch; - } - } - else - { - uint8_t *curPixel = dest; - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 2 && (x + i) < w; i++) - { - row[i] = subblockColors0[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - for (size_t i = 2; i < 4 && (x + i) < w; i++) - { - row[i] = subblockColors1[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - curPixel += destRowPitch; - } - } - if (nonOpaquePunchThroughAlpha) - { - decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); - } - } - - void decodeTBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - // Table C.8, distance index for T and H modes - const auto &block = u.idht.mode.tm; - - int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b); - int g1 = extend_4to8bits(block.TG1); - int b1 = extend_4to8bits(block.TB1); - int r2 = extend_4to8bits(block.TR2); - int g2 = extend_4to8bits(block.TG2); - int b2 = extend_4to8bits(block.TB2); - - static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64}; - const int d = distance[block.Tda << 1 | block.Tdb]; - - const R8G8B8A8 paintColors[4] = { - createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2), - createRGBA(r2 - d, g2 - d, b2 - d), - }; - - uint8_t *curPixel = dest; - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - row[i] = paintColors[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - curPixel += destRowPitch; - } - - if (nonOpaquePunchThroughAlpha) - { - decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); - } - } - - void decodeHBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - // Table C.8, distance index for T and H modes - const auto &block = u.idht.mode.hm; - - int r1 = extend_4to8bits(block.HR1); - int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b); - int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c); - int r2 = extend_4to8bits(block.HR2); - int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b); - int b2 = extend_4to8bits(block.HB2); - - static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64}; - const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | - ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)]; - - const R8G8B8A8 paintColors[4] = { - createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d), - createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d), - }; - - uint8_t *curPixel = dest; - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - row[i] = paintColors[getIndex(i, j)]; - row[i].A = alphaValues[j][i]; - } - curPixel += destRowPitch; - } - - if (nonOpaquePunchThroughAlpha) - { - decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); - } - } - - void decodePlanarBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t pitch, - const uint8_t alphaValues[4][4]) const - { - int ro = extend_6to8bits(u.pblk.RO); - int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2); - int bo = - extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b); - int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2); - int gh = extend_7to8bits(u.pblk.GH); - int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb); - int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb); - int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb); - int bv = extend_6to8bits(u.pblk.BV); - - uint8_t *curPixel = dest; - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - - int ry = static_cast<int>(j) * (rv - ro) + 2; - int gy = static_cast<int>(j) * (gv - go) + 2; - int by = static_cast<int>(j) * (bv - bo) + 2; - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro, - ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go, - ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo, - alphaValues[j][i]); - } - curPixel += pitch; - } - } - - // Index for individual, differential, H and T modes - size_t getIndex(size_t x, size_t y) const - { - size_t bitIndex = x * 4 + y; - size_t bitOffset = bitIndex & 7; - size_t lsb = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; - size_t msb = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; - return (msb << 1) | lsb; - } - - void decodePunchThroughAlphaBlock(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - size_t destRowPitch) const - { - uint8_t *curPixel = dest; - for (size_t j = 0; j < 4 && (y + j) < h; j++) - { - R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel); - for (size_t i = 0; i < 4 && (x + i) < w; i++) - { - if (getIndex(i, j) == 2) // msb == 1 && lsb == 0 - { - row[i] = createRGBA(0, 0, 0, 0); - } - } - curPixel += destRowPitch; - } - } - - uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const - { - return (static_cast<uint16_t>(rgba.R >> 3) << 11) | - (static_cast<uint16_t>(rgba.G >> 2) << 5) | - (static_cast<uint16_t>(rgba.B >> 3) << 0); - } - - uint32_t matchBC1Bits(const R8G8B8A8 *rgba, - const R8G8B8A8 &minColor, - const R8G8B8A8 &maxColor, - bool opaque) const - { - // Project each pixel on the (maxColor, minColor) line to decide which - // BC1 code to assign to it. - - uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B}, - {minColor.R, minColor.G, minColor.B}}; - - int direction[3]; - for (int ch = 0; ch < 3; ch++) - { - direction[ch] = decodedColors[0][ch] - decodedColors[1][ch]; - } - - int stops[2]; - for (int i = 0; i < 2; i++) - { - stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] + - decodedColors[i][2] * direction[2]; - } - - uint32_t bits = 0; - if (opaque) - { - for (int i = 15; i >= 0; i--) - { - // In opaque mode, the code is from 0 to 3. - - bits <<= 2; - const int dot = - rgba[i].R * direction[0] + rgba[i].G * direction[1] + rgba[i].B * direction[2]; - const int factor = gl::clamp( - static_cast<int>( - (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 3 + 0.5f), - 0, 3); - switch (factor) - { - case 0: - bits |= 1; - break; - case 1: - bits |= 3; - break; - case 2: - bits |= 2; - break; - case 3: - default: - bits |= 0; - break; - } - } - } - else - { - for (int i = 15; i >= 0; i--) - { - // In non-opaque mode, 3 is for tranparent pixels. - - bits <<= 2; - if (0 == rgba[i].A) - { - bits |= 3; - } - else - { - const int dot = rgba[i].R * direction[0] + rgba[i].G * direction[1] + - rgba[i].B * direction[2]; - const int factor = gl::clamp( - static_cast<int>( - (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 2 + - 0.5f), - 0, 2); - switch (factor) - { - case 0: - bits |= 0; - break; - case 1: - bits |= 2; - break; - case 2: - default: - bits |= 1; - break; - } - } - } - } - - return bits; - } - - void packBC1(void *bc1, - const R8G8B8A8 *rgba, - R8G8B8A8 &minColor, - R8G8B8A8 &maxColor, - bool opaque) const - { - uint32_t bits; - uint16_t max16 = RGB8ToRGB565(maxColor); - uint16_t min16 = RGB8ToRGB565(minColor); - if (max16 != min16) - { - // Find the best BC1 code for each pixel - bits = matchBC1Bits(rgba, minColor, maxColor, opaque); - } - else - { - // Same colors, BC1 index 0 is the color in both opaque and transparent mode - bits = 0; - // BC1 index 3 is transparent - if (!opaque) - { - for (int i = 0; i < 16; i++) - { - if (0 == rgba[i].A) - { - bits |= (3 << (i * 2)); - } - } - } - } - - if (max16 < min16) - { - std::swap(max16, min16); - - uint32_t xorMask = 0; - if (opaque) - { - // In opaque mode switching the two colors is doing the - // following code swaps: 0 <-> 1 and 2 <-> 3. This is - // equivalent to flipping the first bit of each code - // (5 = 0b0101) - xorMask = 0x55555555; - } - else - { - // In transparent mode switching the colors is doing the - // following code swap: 0 <-> 1. 0xA selects the second bit of - // each code, bits >> 1 selects the first bit of the code when - // the seconds bit is set (case 2 and 3). We invert all the - // non-selected bits, that is the first bit when the code is - // 0 or 1. - xorMask = ~((bits >> 1) | 0xAAAAAAAA); - } - bits ^= xorMask; - } - - struct BC1Block - { - uint16_t color0; - uint16_t color1; - uint32_t bits; - }; - - // Encode the opaqueness in the order of the two BC1 colors - BC1Block *dest = reinterpret_cast<BC1Block *>(bc1); - if (opaque) - { - dest->color0 = max16; - dest->color1 = min16; - } - else - { - dest->color0 = min16; - dest->color1 = max16; - } - dest->bits = bits; - } - - void transcodeIndividualBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - const auto &block = u.idht.mode.idm.colors.indiv; - int r1 = extend_4to8bits(block.R1); - int g1 = extend_4to8bits(block.G1); - int b1 = extend_4to8bits(block.B1); - int r2 = extend_4to8bits(block.R2); - int g2 = extend_4to8bits(block.G2); - int b2 = extend_4to8bits(block.B2); - transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2, - alphaValues, nonOpaquePunchThroughAlpha); - } - - void transcodeDifferentialBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - const auto &block = u.idht.mode.idm.colors.diff; - int b1 = extend_5to8bits(block.B); - int g1 = extend_5to8bits(block.G); - int r1 = extend_5to8bits(block.R); - int r2 = extend_5to8bits(block.R + block.dR); - int g2 = extend_5to8bits(block.G + block.dG); - int b2 = extend_5to8bits(block.B + block.dB); - transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2, - alphaValues, nonOpaquePunchThroughAlpha); - } - - void decodeSubblock(R8G8B8A8 *rgbaBlock, - size_t pixelRange[2][2], - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool flipbit, - size_t subblockIdx, - const R8G8B8A8 subblockColors[2][4]) const - { - size_t dxBegin = 0; - size_t dxEnd = 4; - size_t dyBegin = subblockIdx * 2; - size_t dyEnd = dyBegin + 2; - if (!flipbit) - { - std::swap(dxBegin, dyBegin); - std::swap(dxEnd, dyEnd); - } - - for (size_t j = dyBegin; j < dyEnd && (y + j) < h; j++) - { - R8G8B8A8 *row = &rgbaBlock[j * 4]; - for (size_t i = dxBegin; i < dxEnd && (x + i) < w; i++) - { - const size_t pixelIndex = getIndex(i, j); - if (valueMappingTable[pixelIndex] < valueMappingTable[pixelRange[subblockIdx][0]]) - { - pixelRange[subblockIdx][0] = pixelIndex; - } - if (valueMappingTable[pixelIndex] > valueMappingTable[pixelRange[subblockIdx][1]]) - { - pixelRange[subblockIdx][1] = pixelIndex; - } - - row[i] = subblockColors[subblockIdx][pixelIndex]; - row[i].A = alphaValues[j][i]; - } - } - } - - void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - int r1, - int g1, - int b1, - int r2, - int g2, - int b2, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - // A BC1 block has 2 endpoints, pixels is encoded as linear - // interpolations of them. A ETC1/ETC2 individual or differential block - // has 2 subblocks. Each subblock has one color and a modifier. We - // compute the max intensity and min intensity pixel values to use as - // our two BC1 endpoints and then map pixels to BC1 by projecting on the - // line between the two endpoints and choosing the right fraction. - // - // In the future, we have 2 potential improvements to this algorithm. - // 1. We don't actually need to decode ETC blocks to RGBs. Instead, - // the subblock colors and pixel indices alreay contains enough - // information for transcode. A direct mapping would be more - // efficient here. - // 2. Currently the BC1 endpoints come from the max and min intensity - // of ETC colors. A principal component analysis (PCA) on them might - // give us better quality results, with limited costs - - const auto intensityModifier = - nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; - - // Compute the colors that pixels can have in each subblock both for - // the decoding of the RGBA data and BC1 encoding - R8G8B8A8 subblockColors[2][4]; - for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++) - { - const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx]; - subblockColors[0][modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1); - - const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx]; - subblockColors[1][modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2); - } - - // 1 and 3 are the argmax and argmin of valueMappingTable - size_t pixelRange[2][2] = {{1, 3}, {1, 3}}; - R8G8B8A8 rgbaBlock[16]; - // Decode the block in rgbaBlock and store the inverse valueTableMapping - // of {min(modifier index), max(modifier index)} - for (size_t blockIdx = 0; blockIdx < 2; blockIdx++) - { - decodeSubblock(rgbaBlock, pixelRange, x, y, w, h, alphaValues, u.idht.mode.idm.flipbit, - blockIdx, subblockColors); - } - if (nonOpaquePunchThroughAlpha) - { - decodePunchThroughAlphaBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h, - sizeof(R8G8B8A8) * 4); - } - - // Get the "min" and "max" pixel colors that have been used. - R8G8B8A8 minColor; - const R8G8B8A8 &minColor0 = subblockColors[0][pixelRange[0][0]]; - const R8G8B8A8 &minColor1 = subblockColors[1][pixelRange[1][0]]; - if (minColor0.R + minColor0.G + minColor0.B < minColor1.R + minColor1.G + minColor1.B) - { - minColor = minColor0; - } - else - { - minColor = minColor1; - } - - R8G8B8A8 maxColor; - const R8G8B8A8 &maxColor0 = subblockColors[0][pixelRange[0][1]]; - const R8G8B8A8 &maxColor1 = subblockColors[1][pixelRange[1][1]]; - if (maxColor0.R + maxColor0.G + maxColor0.B < maxColor1.R + maxColor1.G + maxColor1.B) - { - maxColor = maxColor1; - } - else - { - maxColor = maxColor0; - } - - packBC1(dest, rgbaBlock, minColor, maxColor, !nonOpaquePunchThroughAlpha); - } - - void transcodeTBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - // TODO (mgong): Will be implemented soon - UNIMPLEMENTED(); - } - - void transcodeHBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4], - bool nonOpaquePunchThroughAlpha) const - { - // TODO (mgong): Will be implemented soon - UNIMPLEMENTED(); - } - - void transcodePlanarBlockToBC1(uint8_t *dest, - size_t x, - size_t y, - size_t w, - size_t h, - const uint8_t alphaValues[4][4]) const - { - // TODO (mgong): Will be implemented soon - UNIMPLEMENTED(); - } - - // Single channel utility functions - int getSingleChannel(size_t x, size_t y, bool isSigned) const - { - int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us; - return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier; - } - - int getSingleChannelIndex(size_t x, size_t y) const - { - ASSERT(x < 4 && y < 4); - - // clang-format off - switch (x * 4 + y) - { - case 0: return u.scblk.ma; - case 1: return u.scblk.mb; - case 2: return u.scblk.mc1 << 1 | u.scblk.mc2; - case 3: return u.scblk.md; - case 4: return u.scblk.me; - case 5: return u.scblk.mf1 << 2 | u.scblk.mf2; - case 6: return u.scblk.mg; - case 7: return u.scblk.mh; - case 8: return u.scblk.mi; - case 9: return u.scblk.mj; - case 10: return u.scblk.mk1 << 1 | u.scblk.mk2; - case 11: return u.scblk.ml; - case 12: return u.scblk.mm; - case 13: return u.scblk.mn1 << 2 | u.scblk.mn2; - case 14: return u.scblk.mo; - case 15: return u.scblk.mp; - default: UNREACHABLE(); return 0; - } - // clang-format on - } - - int getSingleChannelModifier(size_t x, size_t y) const - { - // clang-format off - static const int modifierTable[16][8] = - { - { -3, -6, -9, -15, 2, 5, 8, 14 }, - { -3, -7, -10, -13, 2, 6, 9, 12 }, - { -2, -5, -8, -13, 1, 4, 7, 12 }, - { -2, -4, -6, -13, 1, 3, 5, 12 }, - { -3, -6, -8, -12, 2, 5, 7, 11 }, - { -3, -7, -9, -11, 2, 6, 8, 10 }, - { -4, -7, -8, -11, 3, 6, 7, 10 }, - { -3, -5, -8, -11, 2, 4, 7, 10 }, - { -2, -6, -8, -10, 1, 5, 7, 9 }, - { -2, -5, -8, -10, 1, 4, 7, 9 }, - { -2, -4, -8, -10, 1, 3, 7, 9 }, - { -2, -5, -7, -10, 1, 4, 6, 9 }, - { -3, -4, -7, -10, 2, 3, 6, 9 }, - { -1, -2, -3, -10, 0, 1, 2, 9 }, - { -4, -6, -8, -9, 3, 5, 7, 8 }, - { -3, -5, -7, -9, 2, 4, 6, 8 } - }; - // clang-format on - - return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)]; - } -}; - -// clang-format off -static const uint8_t DefaultETCAlphaValues[4][4] = -{ - { 255, 255, 255, 255 }, - { 255, 255, 255, 255 }, - { 255, 255, 255, 255 }, - { 255, 255, 255, 255 }, -}; -// clang-format on - -void LoadR11EACToR8(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, - bool isSigned) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y += 4) - { - const ETC2Block *sourceRow = - OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch); - uint8_t *destRow = - OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x += 4) - { - const ETC2Block *sourceBlock = sourceRow + (x / 4); - uint8_t *destPixels = destRow + x; - - sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1, - outputRowPitch, isSigned); - } - } - } -} - -void LoadRG11EACToRG8(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, - bool isSigned) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y += 4) - { - const ETC2Block *sourceRow = - OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch); - uint8_t *destRow = - OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x += 4) - { - uint8_t *destPixelsRed = destRow + (x * 2); - const ETC2Block *sourceBlockRed = sourceRow + (x / 2); - sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2, - outputRowPitch, isSigned); - - uint8_t *destPixelsGreen = destPixelsRed + 1; - const ETC2Block *sourceBlockGreen = sourceBlockRed + 1; - sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2, - outputRowPitch, isSigned); - } - } - } -} - -void LoadETC2RGB8ToRGBA8(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, - bool punchthroughAlpha) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y += 4) - { - const ETC2Block *sourceRow = - OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch); - uint8_t *destRow = - OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x += 4) - { - const ETC2Block *sourceBlock = sourceRow + (x / 4); - uint8_t *destPixels = destRow + (x * 4); - - sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch, - DefaultETCAlphaValues, punchthroughAlpha); - } - } - } -} - -void LoadETC2RGB8ToBC1(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, - bool punchthroughAlpha) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y += 4) - { - const ETC2Block *sourceRow = - OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch); - uint8_t *destRow = - OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x += 4) - { - const ETC2Block *sourceBlock = sourceRow + (x / 4); - uint8_t *destPixels = destRow + (x * 2); - - sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues, - punchthroughAlpha); - } - } - } -} - -void LoadETC2RGBA8ToRGBA8(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, - bool srgb) -{ - uint8_t decodedAlphaValues[4][4]; - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y += 4) - { - const ETC2Block *sourceRow = - OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch); - uint8_t *destRow = - OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x += 4) - { - const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2); - sourceBlockAlpha->decodeAsSingleChannel( - reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4, - false); - - uint8_t *destPixels = destRow + (x * 4); - const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1; - sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch, - decodedAlphaValues, false); - } - } - } -} - -} // anonymous namespace - -void LoadETC1RGB8ToRGBA8(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) -{ - LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadETC1RGB8ToBC1(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) -{ - LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadEACR11ToR8(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) -{ - LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadEACR11SToR8(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) -{ - LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, true); -} - -void LoadEACRG11ToRG8(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) -{ - LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadEACRG11SToRG8(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) -{ - LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, true); -} - -void LoadETC2RGB8ToRGBA8(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) -{ - LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadETC2SRGB8ToRGBA8(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) -{ - LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadETC2RGB8A1ToRGBA8(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) -{ - LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, true); -} - -void LoadETC2SRGB8A1ToRGBA8(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) -{ - LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, true); -} - -void LoadETC2RGBA8ToRGBA8(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) -{ - LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, false); -} - -void LoadETC2SRGBA8ToSRGBA8(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) -{ - LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, - outputRowPitch, outputDepthPitch, true); -} - -} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h deleted file mode 100644 index dc64e0461b..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// 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. -// - -// loadimage_etc.h: Decodes ETC and EAC encoded textures. - -#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ -#define LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ - -#include "libANGLE/angletypes.h" - -#include <stdint.h> - -namespace rx -{ - -void LoadETC1RGB8ToRGBA8(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); - -void LoadETC1RGB8ToBC1(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); - -void LoadEACR11ToR8(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); - -void LoadEACR11SToR8(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); - -void LoadEACRG11ToRG8(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); - -void LoadEACRG11SToRG8(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); - -void LoadETC2RGB8ToRGBA8(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); - -void LoadETC2SRGB8ToRGBA8(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); - -void LoadETC2RGB8A1ToRGBA8(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); - -void LoadETC2SRGB8A1ToRGBA8(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); - -void LoadETC2RGBA8ToRGBA8(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); - -void LoadETC2SRGBA8ToSRGBA8(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); -} - -#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ |