diff options
Diffstat (limited to 'chromium/third_party/angle/src/libANGLE/renderer')
138 files changed, 16244 insertions, 3886 deletions
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h index eb150549e14..550bc1e2d9a 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h @@ -26,9 +26,10 @@ class DeviceImpl : angle::NonCopyable DeviceImpl(); virtual ~DeviceImpl(); - virtual egl::Error getDevice(EGLAttrib *value) = 0; + virtual egl::Error getDevice(void **outValue) = 0; virtual EGLint getType() = 0; virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0; + virtual bool deviceExternallySourced() = 0; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp b/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp index 2eb44eb5ba1..8061189f0a7 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp @@ -21,10 +21,7 @@ DisplayImpl::DisplayImpl() DisplayImpl::~DisplayImpl() { - while (!mSurfaceSet.empty()) - { - destroySurface(*mSurfaceSet.begin()); - } + ASSERT(mSurfaceSet.empty()); } void DisplayImpl::destroySurface(egl::Surface *surface) diff --git a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h index dddd9b87788..a9ae37891ea 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h @@ -44,10 +44,23 @@ class FramebufferImpl : angle::NonCopyable virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0; virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; - virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; - virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; - virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; - virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + virtual gl::Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) = 0; + virtual gl::Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) = 0; + virtual gl::Error clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) = 0; + virtual gl::Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) = 0; virtual GLenum getImplementationColorReadFormat() const = 0; virtual GLenum getImplementationColorReadType() const = 0; @@ -56,7 +69,7 @@ class FramebufferImpl : angle::NonCopyable virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0; - virtual GLenum checkStatus() const = 0; + virtual bool checkStatus() const = 0; const gl::Framebuffer::Data &getData() const { return mData; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h new file mode 100644 index 00000000000..b5a1eded586 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h @@ -0,0 +1,65 @@ +// +// 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. +// +// FramebufferImpl_mock.h: +// Defines a mock of the FramebufferImpl class. +// + +#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ +#define LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace rx +{ + +class MockFramebufferImpl : public rx::FramebufferImpl +{ + public: + MockFramebufferImpl() : rx::FramebufferImpl(gl::Framebuffer::Data()) {} + virtual ~MockFramebufferImpl() { destroy(); } + + MOCK_METHOD1(onUpdateColorAttachment, void(size_t)); + MOCK_METHOD0(onUpdateDepthAttachment, void()); + MOCK_METHOD0(onUpdateStencilAttachment, void()); + MOCK_METHOD0(onUpdateDepthStencilAttachment, void()); + + MOCK_METHOD2(setDrawBuffers, void(size_t, const GLenum *)); + MOCK_METHOD1(setReadBuffer, void(GLenum)); + + MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *)); + MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *)); + MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &)); + + MOCK_METHOD2(clear, gl::Error(const gl::Data &, GLbitfield)); + MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Data &, GLenum, GLint, const GLfloat *)); + MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Data &, GLenum, GLint, const GLuint *)); + MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Data &, GLenum, GLint, const GLint *)); + MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Data &, GLenum, GLint, GLfloat, GLint)); + + MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum()); + MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum()); + MOCK_CONST_METHOD5( + readPixels, + gl::Error(const gl::State &, const gl::Rectangle &, GLenum, GLenum, GLvoid *)); + + MOCK_METHOD6(blit, + gl::Error(const gl::State &, + const gl::Rectangle &, + const gl::Rectangle &, + GLbitfield, + GLenum, + const gl::Framebuffer *)); + + MOCK_CONST_METHOD0(checkStatus, bool()); + + MOCK_METHOD0(destroy, void()); +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h index a94f04b20c4..1e688045a1b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h @@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; + virtual void setBinaryRetrievableHint(bool retrievable) = 0; virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0; virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0; @@ -66,9 +67,14 @@ class ProgramImpl : angle::NonCopyable // TODO: synchronize in syncState when dirty bits exist. virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; - // Gather uniform block active uniform indices, and uniform block offset info. - virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks, - std::vector<gl::LinkedUniform> *uniforms) = 0; + // May only be called after a successful link operation. + // Return false for inactive blocks. + virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0; + + // May only be called after a successful link operation. + // Returns false for inactive members. + virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const = 0; protected: const gl::Program::Data &mData; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h new file mode 100644 index 00000000000..0db2330228d --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h @@ -0,0 +1,65 @@ +// +// 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. +// +// ProgramImpl_mock.h: +// Defines a mock of the ProgramImpl class. +// + +#ifndef LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ +#define LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/ProgramImpl.h" + +namespace rx +{ + +class MockProgramImpl : public rx::ProgramImpl +{ + public: + MockProgramImpl() : ProgramImpl(gl::Program::Data()) {} + virtual ~MockProgramImpl() { destroy(); } + + MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *)); + MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *)); + MOCK_METHOD1(setBinaryRetrievableHint, void(bool)); + + MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &)); + MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *)); + + MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform2fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform3fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform4fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform1iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform2iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform3iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform4iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform1uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform2uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform3uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform4uiv, void(GLint, GLsizei, const GLuint *)); + + MOCK_METHOD4(setUniformMatrix2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix2x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix2x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + + MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint)); + MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *)); + MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *)); + + MOCK_METHOD0(destroy, void()); +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h b/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h index 06fe560d5c2..b20dcaf0fc3 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h @@ -82,7 +82,6 @@ class Renderer : public ImplFactory virtual bool testDeviceLost() = 0; virtual bool testDeviceResettable() = 0; - virtual VendorID getVendorId() const = 0; virtual std::string getVendorString() const = 0; virtual std::string getRendererDescription() const = 0; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h index ec164f3f7fc..5a466377a53 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h @@ -22,12 +22,15 @@ class ShaderImpl : angle::NonCopyable virtual ~ShaderImpl() { } // Returns additional ShCompile options. - virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream) = 0; + virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) = 0; // Returns success for compiling on the driver. Returns success. virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0; virtual std::string getDebugInfo() const = 0; + const gl::Shader::Data &getData() const { return mData; } + protected: const gl::Shader::Data &mData; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h index 1d5211bb9a9..32125d542c4 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h @@ -36,7 +36,7 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl virtual egl::Error swap() = 0; virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0; virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0; - virtual egl::Error bindTexImage(EGLint buffer) = 0; + virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0; virtual egl::Error releaseTexImage(EGLint buffer) = 0; virtual void setSwapInterval(EGLint interval) = 0; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp index 693b27116fa..ffca99c3ac6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -8,6 +8,7 @@ #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "common/mathutil.h" #include "common/utilities.h" #include "libANGLE/renderer/d3d/IndexBuffer.h" #include "libANGLE/renderer/d3d/VertexBuffer.h" @@ -22,6 +23,9 @@ BufferD3D::BufferD3D(BufferFactoryD3D *factory) mFactory(factory), mStaticVertexBuffer(nullptr), mStaticIndexBuffer(nullptr), + mStaticBufferCache(nullptr), + mStaticBufferCacheTotalSize(0), + mStaticVertexBufferOutOfDate(false), mUnmodifiedDataUse(0), mUsage(D3D_BUFFER_USAGE_STATIC) { @@ -32,6 +36,19 @@ BufferD3D::~BufferD3D() { SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticIndexBuffer); + + emptyStaticBufferCache(); +} + +void BufferD3D::emptyStaticBufferCache() +{ + if (mStaticBufferCache != nullptr) + { + SafeDeleteContainer(*mStaticBufferCache); + SafeDelete(mStaticBufferCache); + } + + mStaticBufferCacheTotalSize = 0; } void BufferD3D::updateSerial() @@ -75,8 +92,124 @@ void BufferD3D::initializeStaticData() } } -void BufferD3D::invalidateStaticData() +StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer() +{ + return mStaticIndexBuffer; +} + +StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer( + const gl::VertexAttribute &attribute, + D3DStaticBufferCreationType creationType) +{ + if (!mStaticVertexBuffer) + { + // 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 or is already in there + return mStaticVertexBuffer; + } + + // At this point, see if any of the existing static buffers contains the attribute data + + // If the default static vertex buffer contains the attribute, then return it + if (mStaticVertexBuffer->lookupAttribute(attribute, nullptr)) + { + return mStaticVertexBuffer; + } + + if (mStaticBufferCache != nullptr) + { + // If there is a cached static buffer that already contains the attribute, then return it + for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache) + { + if (staticBuffer->lookupAttribute(attribute, nullptr)) + { + return staticBuffer; + } + } + } + + 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; + } + + // At this point, we must create a new static buffer for the attribute data + if (creationType != D3D_BUFFER_CREATE_IF_NECESSARY) + { + return nullptr; + } + + ASSERT(mStaticVertexBuffer); + ASSERT(mStaticVertexBuffer->isCommitted()); + unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize(); + if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize)) + { + // 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; + } + } + + // 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; +} + +void BufferD3D::reinitOutOfDateStaticData() { + 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; + } +} + +void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType) +{ + if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr) + { + emptyStaticBufferCache(); + } + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) { SafeDelete(mStaticVertexBuffer); @@ -98,6 +231,10 @@ void BufferD3D::promoteStaticUsage(int dataSize) { if (!mStaticVertexBuffer && !mStaticIndexBuffer) { + // 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()) diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h index 239b7fb9f0c..a27ca9857af 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -13,6 +13,7 @@ #include "libANGLE/renderer/BufferImpl.h" #include <stdint.h> +#include <vector> namespace rx { @@ -26,6 +27,18 @@ enum D3DBufferUsage D3D_BUFFER_USAGE_DYNAMIC, }; +enum D3DBufferInvalidationType +{ + D3D_BUFFER_INVALIDATE_WHOLE_CACHE, + D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY, +}; + +enum D3DStaticBufferCreationType +{ + D3D_BUFFER_CREATE_IF_NECESSARY, + D3D_BUFFER_DO_NOT_CREATE, +}; + class BufferD3D : public BufferImpl { public: @@ -39,11 +52,14 @@ class BufferD3D : public BufferImpl virtual void markTransformFeedbackUsage() = 0; virtual gl::Error getData(const uint8_t **outData) = 0; - StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } - StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute, + D3DStaticBufferCreationType creationType); + StaticIndexBufferInterface *getStaticIndexBuffer(); void initializeStaticData(); - void invalidateStaticData(); + void invalidateStaticData(D3DBufferInvalidationType invalidationType); + void reinitOutOfDateStaticData(); + void promoteStaticUsage(int dataSize); gl::Error getIndexRange(GLenum type, @@ -55,6 +71,7 @@ class BufferD3D : public BufferImpl protected: void updateSerial(); void updateD3DBufferUsage(GLenum usage); + void emptyStaticBufferCache(); BufferFactoryD3D *mFactory; unsigned int mSerial; @@ -62,6 +79,9 @@ class BufferD3D : public BufferImpl StaticVertexBufferInterface *mStaticVertexBuffer; StaticIndexBufferInterface *mStaticIndexBuffer; + std::vector<StaticVertexBufferInterface *> *mStaticBufferCache; + unsigned int mStaticBufferCacheTotalSize; + unsigned int mStaticVertexBufferOutOfDate; unsigned int mUnmodifiedDataUse; D3DBufferUsage mUsage; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp index 938703ac151..f40e6e6cab5 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp @@ -17,33 +17,81 @@ namespace rx { -DeviceD3D::DeviceD3D(rx::RendererD3D *renderer) - : mRenderer(renderer) +DeviceD3D::DeviceD3D() + : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false) { } -egl::Error DeviceD3D::getDevice(EGLAttrib *value) +DeviceD3D::~DeviceD3D() { - *value = reinterpret_cast<EGLAttrib>(mRenderer->getD3DDevice()); - if (*value == 0) +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) { + // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it. + ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice); + device->Release(); + } +#endif +} + +egl::Error DeviceD3D::getDevice(void **outValue) +{ + if (!mIsInitialized) + { + *outValue = nullptr; return egl::Error(EGL_BAD_DEVICE_EXT); } + + *outValue = mDevice; return egl::Error(EGL_SUCCESS); } -EGLint DeviceD3D::getType() +egl::Error DeviceD3D::initialize(void *device, + EGLint deviceType, + EGLBoolean deviceExternallySourced) { - switch (mRenderer->getRendererClass()) + ASSERT(!mIsInitialized); + if (mIsInitialized) { - case RENDERER_D3D11: - return EGL_D3D11_DEVICE_ANGLE; - case RENDERER_D3D9: - return EGL_D3D9_DEVICE_ANGLE; - default: - UNREACHABLE(); - return EGL_NONE; + return egl::Error(EGL_BAD_DEVICE_EXT); } + + mDevice = device; + mDeviceType = deviceType; + mDeviceExternallySourced = !!deviceExternallySourced; + +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + { + // Validate the device + IUnknown *iunknown = reinterpret_cast<IUnknown *>(device); + + ID3D11Device *d3dDevice = nullptr; + HRESULT hr = + iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice)); + if (FAILED(hr)) + { + return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT"); + } + + // The QI to ID3D11Device adds a ref to the D3D11 device. + // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the + // D3D11 device. + } + else +#endif + { + ASSERT(!mDeviceExternallySourced); + } + + mIsInitialized = true; + + return egl::Error(EGL_SUCCESS); +} + +EGLint DeviceD3D::getType() +{ + return mDeviceType; } void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h index 5f985463452..1dd99797085 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h @@ -18,14 +18,20 @@ namespace rx class DeviceD3D : public DeviceImpl { public: - DeviceD3D(RendererD3D *renderer); + DeviceD3D(); + ~DeviceD3D() override; - egl::Error getDevice(EGLAttrib *value) override; + egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external); + egl::Error getDevice(void **outValue) override; EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; + bool deviceExternallySourced() override { return mDeviceExternallySourced; } private: - RendererD3D *mRenderer; + void *mDevice; + EGLint mDeviceType; + bool mDeviceExternallySourced; + bool mIsInitialized; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp index 46d08a3d4d7..740bc761c65 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -55,10 +55,13 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) std::vector<CreateRendererD3DFunction> rendererCreationFunctions; - const auto &attribMap = display->getAttributeMap(); - EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + 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 = + 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 || @@ -77,27 +80,41 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) } # endif - if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && - nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) - { + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { // The default display is requested, try the D3D9 and D3D11 renderers, order them using // the definition of ANGLE_DEFAULT_D3D11 # if ANGLE_DEFAULT_D3D11 # if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); # endif # if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); # endif # else # if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); # endif # if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); # endif # endif + } + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { +#if defined(ANGLE_ENABLE_D3D11) + if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +#endif + } + else + { + UNIMPLEMENTED(); } egl::Error result(EGL_NOT_INITIALIZED, "No available renderers."); @@ -141,9 +158,7 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) return result; } -DisplayD3D::DisplayD3D() - : mRenderer(nullptr), - mDevice(nullptr) +DisplayD3D::DisplayD3D() : mRenderer(nullptr) { } @@ -157,6 +172,8 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration, 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) { @@ -164,8 +181,8 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration, height = -1; } - return SurfaceD3D::createFromWindow( - mRenderer, mDisplay, configuration, window, fixedSize, width, height); + return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, + directComposition, width, height, orientation); } SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration, @@ -209,9 +226,7 @@ ImageImpl *DisplayD3D::createImage(EGLenum target, egl::Error DisplayD3D::getDevice(DeviceImpl **device) { - *device = reinterpret_cast<DeviceImpl*>(mDevice); - ASSERT(*device != nullptr); - return egl::Error(EGL_SUCCESS); + return mRenderer->getEGLDevice(device); } egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, @@ -222,8 +237,10 @@ egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Contex EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT); bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); + bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE); - *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess); + *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, + robustAccess, debug); return egl::Error(EGL_SUCCESS); } @@ -242,15 +259,11 @@ egl::Error DisplayD3D::initialize(egl::Display *display) return error; } - ASSERT(mDevice == nullptr); - mDevice = new DeviceD3D(mRenderer); - return egl::Error(EGL_SUCCESS); } void DisplayD3D::terminate() { - SafeDelete(mDevice); SafeDelete(mRenderer); } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h index 973b77aa1a5..7ce78daea5b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -65,8 +65,6 @@ class DisplayD3D : public DisplayImpl egl::Display *mDisplay; rx::RendererD3D *mRenderer; - - DeviceImpl *mDevice; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index 6e386f937c2..1d07b95c333 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -13,11 +13,10 @@ #include "libANGLE/Program.h" #include "libANGLE/Shader.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h" - -// For use with ArrayString, see angleutils.h -static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int."); +#include "libANGLE/renderer/d3d/VaryingPacking.h" using namespace gl; @@ -31,12 +30,17 @@ std::string HLSLComponentTypeString(GLenum componentType) { switch (componentType) { - case GL_UNSIGNED_INT: return "uint"; - case GL_INT: return "int"; - case GL_UNSIGNED_NORMALIZED: - case GL_SIGNED_NORMALIZED: - case GL_FLOAT: return "float"; - default: UNREACHABLE(); return "not-component-type"; + case GL_UNSIGNED_INT: + return "uint"; + case GL_INT: + return "int"; + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + return "float"; + default: + UNREACHABLE(); + return "not-component-type"; } } @@ -49,16 +53,27 @@ std::string HLSLMatrixTypeString(GLenum type) { switch (type) { - case GL_FLOAT_MAT2: return "float2x2"; - case GL_FLOAT_MAT3: return "float3x3"; - case GL_FLOAT_MAT4: return "float4x4"; - case GL_FLOAT_MAT2x3: return "float2x3"; - case GL_FLOAT_MAT3x2: return "float3x2"; - case GL_FLOAT_MAT2x4: return "float2x4"; - case GL_FLOAT_MAT4x2: return "float4x2"; - case GL_FLOAT_MAT3x4: return "float3x4"; - case GL_FLOAT_MAT4x3: return "float4x3"; - default: UNREACHABLE(); return "not-matrix-type"; + case GL_FLOAT_MAT2: + return "float2x2"; + case GL_FLOAT_MAT3: + return "float3x3"; + case GL_FLOAT_MAT4: + return "float4x4"; + case GL_FLOAT_MAT2x3: + return "float2x3"; + case GL_FLOAT_MAT3x2: + return "float3x2"; + case GL_FLOAT_MAT2x4: + return "float2x4"; + case GL_FLOAT_MAT4x2: + return "float4x2"; + case GL_FLOAT_MAT3x4: + return "float3x4"; + case GL_FLOAT_MAT4x3: + return "float4x3"; + default: + UNREACHABLE(); + return "not-matrix-type"; } } @@ -69,11 +84,13 @@ std::string HLSLTypeString(GLenum type) return HLSLMatrixTypeString(type); } - return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); + return HLSLComponentTypeString(gl::VariableComponentType(type), + gl::VariableComponentCount(type)); } -const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables, - unsigned int location) +const PixelShaderOutputVariable *FindOutputAtLocation( + const std::vector<PixelShaderOutputVariable> &outputVariables, + unsigned int location) { for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) { @@ -83,329 +100,102 @@ const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelSha } } - return NULL; + return nullptr; } -typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; - -bool PackVarying(PackedVarying *packedVarying, const int maxVaryingVectors, VaryingPacking &packing) +void WriteArrayString(std::stringstream &strstr, unsigned int i) { - // Make sure we use transposed matrix types to count registers correctly. - int registers = 0; - int elements = 0; - - const sh::Varying &varying = *packedVarying->varying; - - if (varying.isStruct()) - { - registers = HLSLVariableRegisterCount(varying, true) * varying.elementCount(); - elements = 4; - } - else - { - GLenum transposedType = TransposeMatrixType(varying.type); - registers = VariableRowCount(transposedType) * varying.elementCount(); - elements = VariableColumnCount(transposedType); - } - - if (elements >= 2 && elements <= 4) - { - for (int r = 0; r <= maxVaryingVectors - registers; r++) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 0; x < elements && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - packedVarying->registerIndex = r; - packedVarying->columnIndex = 0; - - for (int y = 0; y < registers; y++) - { - for (int x = 0; x < elements; x++) - { - packing[r + y][x] = packedVarying; - } - } - - return true; - } - } - - if (elements == 2) - { - for (int r = maxVaryingVectors - registers; r >= 0; r--) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 2; x < 4 && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - packedVarying->registerIndex = r; - packedVarying->columnIndex = 2; - - for (int y = 0; y < registers; y++) - { - for (int x = 2; x < 4; x++) - { - packing[r + y][x] = packedVarying; - } - } - - return true; - } - } - } - } - else if (elements == 1) + static_assert(GL_INVALID_INDEX == UINT_MAX, + "GL_INVALID_INDEX must be equal to the max unsigned int."); + if (i == UINT_MAX) { - int space[4] = { 0 }; - - for (int y = 0; y < maxVaryingVectors; y++) - { - for (int x = 0; x < 4; x++) - { - space[x] += packing[y][x] ? 0 : 1; - } - } - - int column = 0; - - for (int x = 0; x < 4; x++) - { - if (space[x] >= registers && (space[column] < registers || space[x] < space[column])) - { - column = x; - } - } - - if (space[column] >= registers) - { - for (int r = 0; r < maxVaryingVectors; r++) - { - if (!packing[r][column]) - { - packedVarying->registerIndex = r; - packedVarying->columnIndex = column; - - for (int y = r; y < r + registers; y++) - { - packing[y][column] = packedVarying; - } - - break; - } - } - - return true; - } + return; } - else UNREACHABLE(); - return false; + strstr << "["; + strstr << i; + strstr << "]"; } const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; -} +} // anonymous namespace -DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) +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"); } -// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 -// Returns the number of used varying registers, or -1 if unsuccesful -int DynamicHLSL::packVaryings(InfoLog &infoLog, - std::vector<PackedVarying> *packedVaryings, - const std::vector<std::string> &transformFeedbackVaryings) -{ - // TODO (geofflang): Use context's caps - const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; - - VaryingPacking packing = {}; - - std::set<std::string> uniqueVaryingNames; +// DynamicHLSL implementation - for (PackedVarying &packedVarying : *packedVaryings) - { - const sh::Varying &varying = *packedVarying.varying; - - // Do not assign registers to built-in or unreferenced varyings - if (varying.isBuiltIn() || !varying.staticUse) - { - continue; - } - - ASSERT(uniqueVaryingNames.count(varying.name) == 0); - - if (PackVarying(&packedVarying, maxVaryingVectors, packing)) - { - uniqueVaryingNames.insert(varying.name); - } - else - { - infoLog << "Could not pack varying " << varying.name; - return -1; - } - } - - for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings) - { - if (transformFeedbackVaryingName == "gl_Position" || - transformFeedbackVaryingName == "gl_PointSize") - { - // do not pack builtin XFB varyings - continue; - } - - if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0) - { - bool found = false; - for (PackedVarying &packedVarying : *packedVaryings) - { - const sh::Varying &varying = *packedVarying.varying; - if (transformFeedbackVaryingName == varying.name) - { - if (!PackVarying(&packedVarying, maxVaryingVectors, packing)) - { - infoLog << "Could not pack varying " << varying.name; - return -1; - } - - found = true; - break; - } - } - - if (!found) - { - infoLog << "Transform feedback varying " << transformFeedbackVaryingName - << " does not exist in the vertex shader."; - return -1; - } - } - } - - // Return the number of used registers - int registers = 0; - - for (int r = 0; r < maxVaryingVectors; r++) - { - if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) - { - registers++; - } - } - - return registers; +DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) +{ } -std::string DynamicHLSL::generateVaryingHLSL(const std::vector<PackedVarying> &varyings, - bool shaderUsesPointSize) const +void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking, + std::stringstream &hlslStream) const { - std::string varyingSemantic = getVaryingSemantic(shaderUsesPointSize); - std::string varyingHLSL; - - for (const PackedVarying &packedVarying : varyings) - { - if (!packedVarying.registerAssigned()) - { - continue; - } - - const sh::Varying &varying = *packedVarying.varying; - - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - for (int row = 0; row < variableRows; row++) - { - // 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 (varying.interpolation) - { - case sh::INTERPOLATION_SMOOTH: - varyingHLSL += " "; - break; - case sh::INTERPOLATION_FLAT: - varyingHLSL += " nointerpolation "; - break; - case sh::INTERPOLATION_CENTROID: - varyingHLSL += " centroid "; - break; - default: - UNREACHABLE(); - } - - unsigned int semanticIndex = - elementIndex * variableRows + - packedVarying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + - packedVarying.registerIndex + row; - std::string n = Str(semanticIndex); - - std::string typeString; - - if (varying.isStruct()) - { - // TODO(jmadill): pass back translated name from the shader translator - typeString = decorateVariable(varying.structName); - } - else - { - GLenum componentType = VariableComponentType(transposedType); - int columnCount = VariableColumnCount(transposedType); - typeString = HLSLComponentTypeString(componentType, columnCount); - } - varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; - } - } + 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"; } - - return varyingHLSL; } -std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, - const InputLayout &inputLayout, - const std::vector<sh::Attribute> &shaderAttributes) const +std::string DynamicHLSL::generateVertexShaderForInputLayout( + const std::string &sourceShader, + const InputLayout &inputLayout, + const std::vector<sh::Attribute> &shaderAttributes) const { - std::string structHLSL, initHLSL; + std::stringstream structStream; + std::stringstream initStream; + + structStream << "struct VS_INPUT\n" + << "{\n"; - int semanticIndex = 0; + int semanticIndex = 0; unsigned int inputIndex = 0; // If gl_PointSize is used in the shader then pointsprites rendering is expected. // If the renderer does not support Geometry shaders then Instanced PointSprite emulation // must be used. bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; - bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + bool useInstancedPointSpriteEmulation = + usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; // Instanced PointSprite emulation requires additional entries in the // VS_INPUT structure to support the vertices that make up the quad vertices. @@ -417,8 +207,8 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s // before per instance data in the shader. if (useInstancedPointSpriteEmulation) { - structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n"; - structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; + structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n" + << " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; } for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex) @@ -434,7 +224,8 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s if (IsMatrixType(shaderAttribute.type)) { // Matrix types are always transposed - structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); + structStream << " " + << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); } else { @@ -442,31 +233,34 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s if (shaderAttribute.name == "gl_InstanceID") { - // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int). - structHLSL += " uint"; + // The input type of the instance ID in HLSL (uint) differs from the one in ESSL + // (int). + structStream << " uint"; } else { - structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); + structStream << " " << HLSLComponentTypeString( + componentType, + VariableComponentCount(shaderAttribute.type)); } } - structHLSL += " " + decorateVariable(shaderAttribute.name) + " : "; + structStream << " " << decorateVariable(shaderAttribute.name) << " : "; if (shaderAttribute.name == "gl_InstanceID") { - structHLSL += "SV_InstanceID"; + structStream << "SV_InstanceID"; } else { - structHLSL += "TEXCOORD" + Str(semanticIndex); + structStream << "TEXCOORD" << semanticIndex; semanticIndex += VariableRegisterCount(shaderAttribute.type); } - structHLSL += ";\n"; + structStream << ";\n"; // HLSL code for initialization - initHLSL += " " + 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) @@ -474,46 +268,48 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s if (IsMatrixType(shaderAttribute.type) || (mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0) { - initHLSL += generateAttributeConversionHLSL(vertexFormatType, shaderAttribute); + initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute); } else { - initHLSL += "input." + decorateVariable(shaderAttribute.name); + initStream << "input." << decorateVariable(shaderAttribute.name); } - initHLSL += ";\n"; + initStream << ";\n"; inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); } } - std::string replacementHLSL = "struct VS_INPUT\n" - "{\n" + - structHLSL + - "};\n" - "\n" - "void initAttributes(VS_INPUT input)\n" - "{\n" + - initHLSL + - "}\n"; + structStream << "};\n" + "\n" + "void initAttributes(VS_INPUT input)\n" + "{\n" + << initStream.str() << "}\n"; std::string vertexHLSL(sourceShader); size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); - vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL); + vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str()); return vertexHLSL; } -std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables, - bool usesFragDepth, const std::vector<GLenum> &outputLayout) const +std::string DynamicHLSL::generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector<PixelShaderOutputVariable> &outputVariables, + bool usesFragDepth, + const std::vector<GLenum> &outputLayout) const { - const int shaderModel = mRenderer->getMajorShaderModel(); + const int shaderModel = mRenderer->getMajorShaderModel(); std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; - std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; - std::string declarationHLSL; - std::string copyHLSL; + std::stringstream declarationStream; + std::stringstream copyStream; + + declarationStream << "struct PS_OUTPUT\n" + "{\n"; for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) { @@ -523,702 +319,576 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string { unsigned int location = (binding - GL_COLOR_ATTACHMENT0); - const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location); + const PixelShaderOutputVariable *outputVariable = + FindOutputAtLocation(outputVariables, location); // OpenGL ES 3.0 spec $4.2.1 - // If [...] not all user-defined output variables are written, the values of fragment colors + // If [...] not all user-defined output variables are written, the values of fragment + // colors // corresponding to unwritten variables are similarly undefined. if (outputVariable) { - declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " + - outputVariable->name + " : " + targetSemantic + - Str(static_cast<int>(layoutIndex)) + ";\n"; + declarationStream << " " + HLSLTypeString(outputVariable->type) << " " + << outputVariable->name << " : " << targetSemantic + << static_cast<int>(layoutIndex) << ";\n"; - copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n"; + copyStream << " output." << outputVariable->name << " = " + << outputVariable->source << ";\n"; } } } if (usesFragDepth) { - declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n"; - copyHLSL += " output.gl_Depth = gl_Depth; \n"; + declarationStream << " float gl_Depth : " << depthSemantic << ";\n"; + copyStream << " output.gl_Depth = gl_Depth; \n"; } - std::string replacementHLSL = "struct PS_OUTPUT\n" - "{\n" + - declarationHLSL + - "};\n" - "\n" - "PS_OUTPUT generateOutput()\n" - "{\n" - " PS_OUTPUT output;\n" + - copyHLSL + - " return output;\n" - "}\n"; + declarationStream << "};\n" + "\n" + "PS_OUTPUT generateOutput()\n" + "{\n" + " PS_OUTPUT output;\n" + << copyStream.str() << " return output;\n" + "}\n"; std::string pixelHLSL(sourceShader); size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); - pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL); + pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), + declarationStream.str()); return pixelHLSL; } -std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const -{ - // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) - // In D3D11 we manually compute gl_PointCoord in the GS. - int shaderModel = mRenderer->getMajorShaderModel(); - return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD"); -} - -struct DynamicHLSL::SemanticInfo -{ - struct BuiltinInfo - { - BuiltinInfo() - : enabled(false), - index(0), - systemValue(false) - {} - - bool enabled; - std::string semantic; - unsigned int index; - bool systemValue; - - std::string str() const - { - return (systemValue ? semantic : (semantic + Str(index))); - } - - void enableSystem(const std::string &systemValueSemantic) - { - enabled = true; - semantic = systemValueSemantic; - systemValue = true; - } - - void enable(const std::string &semanticVal, unsigned int indexVal) - { - enabled = true; - semantic = semanticVal; - index = indexVal; - } - }; - - BuiltinInfo dxPosition; - BuiltinInfo glPosition; - BuiltinInfo glFragCoord; - BuiltinInfo glPointCoord; - BuiltinInfo glPointSize; -}; - -DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool position, bool fragCoord, - bool pointCoord, bool pointSize, bool pixelShader) const -{ - SemanticInfo info; - bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); - const std::string &varyingSemantic = getVaryingSemantic(pointSize); - - int reservedRegisterIndex = startRegisters; - - if (hlsl4) - { - info.dxPosition.enableSystem("SV_Position"); - } - else if (pixelShader) - { - info.dxPosition.enableSystem("VPOS"); - } - else - { - info.dxPosition.enableSystem("POSITION"); - } - - if (position) - { - info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); - } - - if (fragCoord) - { - info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - - 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) - { - info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - else - { - info.glPointCoord.enable("TEXCOORD", 0); - } - } - - // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders - if (pointSize && (!pixelShader || hlsl4)) - { - info.glPointSize.enableSystem("PSIZE"); - } - - return info; -} - -std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const +void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType, + const VaryingPacking &varyingPacking, + std::stringstream &linkStream) const { - std::string linkHLSL = "{\n"; - - ASSERT(info.dxPosition.enabled); - linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; - - if (info.glPosition.enabled) - { - linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; - } - - if (info.glFragCoord.enabled) - { - linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n"; - } - - if (info.glPointCoord.enabled) - { - linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; - } + const auto &builtins = varyingPacking.builtins(shaderType); + ASSERT(builtins.dxPosition.enabled); + linkStream << "{\n" + << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; - if (info.glPointSize.enabled) + if (builtins.glPosition.enabled) { - linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; + linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; } - // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register. - linkHLSL += varyingHLSL; - - linkHLSL += "};\n"; - - return linkHLSL; -} - -void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, - std::vector<LinkedVarying> *linkedVaryings) const -{ - if (info.glPosition.enabled) + if (builtins.glFragCoord.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, - info.glPosition.index, 1)); + linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; } - if (info.glFragCoord.enabled) + if (builtins.glPointCoord.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic, - info.glFragCoord.index, 1)); + linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; } - if (info.glPointSize.enabled) + if (builtins.glPointSize.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); + linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; } -} - -void DynamicHLSL::storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings, - bool shaderUsesPointSize, - std::vector<LinkedVarying> *linkedVaryings) const -{ - const std::string &varyingSemantic = getVaryingSemantic(shaderUsesPointSize); - - for (const PackedVarying &packedVarying : packedVaryings) - { - if (packedVarying.registerAssigned()) - { - const sh::Varying &varying = *packedVarying.varying; - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the + // same register. + generateVaryingHLSL(varyingPacking, linkStream); - linkedVaryings->push_back( - LinkedVarying(varying.name, varying.type, varying.elementCount(), varyingSemantic, - packedVarying.registerIndex, variableRows * varying.elementCount())); - } - } + linkStream << "};\n"; } bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, const gl::Program::Data &programData, - InfoLog &infoLog, - int registers, - std::string &pixelHLSL, - std::string &vertexHLSL, - const std::vector<PackedVarying> &packedVaryings, - std::vector<LinkedVarying> *linkedVaryings, - std::vector<PixelShaderOutputVariable> *outPixelShaderKey, - bool *outUsesFragDepth) const + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const { - if (pixelHLSL.empty() || vertexHLSL.empty()) - { - return false; - } + ASSERT(pixelHLSL->empty() && vertexHLSL->empty()); const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader(); const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(vertexShaderGL); const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader(); const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL); + const int shaderModel = mRenderer->getMajorShaderModel(); - bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; - bool usesFragCoord = fragmentShader->mUsesFragCoord; - bool usesPointCoord = fragmentShader->mUsesPointCoord; - bool usesPointSize = vertexShader->mUsesPointSize; - bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + bool useInstancedPointSpriteEmulation = + programMetadata.usesPointSize() && + mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; // Validation done in the compiler - ASSERT(!fragmentShader->mUsesFragColor || !fragmentShader->mUsesFragData); - - // Write the HLSL input/output declarations - const int shaderModel = mRenderer->getMajorShaderModel(); - const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); - - // Two cases when writing to gl_FragColor and using ESSL 1.0: - // - with a 3.0 context, the output color is copied to channel 0 - // - with a 2.0 context, the output color is broadcast to all channels - const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); - - // gl_Position only needs to be outputted from the vertex shader if transform feedback is active. - // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case. - // This saves us 1 output vector. - bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""); - - int shaderVersion = vertexShaderGL->getShaderVersion(); - - if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors) - { - infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord"; - return false; - } + ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); - const std::string &varyingHLSL = generateVaryingHLSL(packedVaryings, usesPointSize); - - // Instanced PointSprite emulation requires 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. - const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS, - usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord), - (!useInstancedPointSpriteEmulation && usesPointSize), false); - - storeUserLinkedVaryings(packedVaryings, usesPointSize, linkedVaryings); - storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); + std::stringstream vertexStream; + vertexStream << vertexShaderGL->getTranslatedSource(); // Instanced PointSprite emulation requires additional entries originally generated in the - // GeometryShader HLSL. These include pointsize clamp values. + // GeometryShader HLSL. These include pointsize clamp values. if (useInstancedPointSpriteEmulation) { - vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" - "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"; + vertexStream << "static float minPointSize = " + << static_cast<int>(data.caps->minAliasedPointSize) << ".0f;\n" + << "static float maxPointSize = " + << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n"; } // Add stub string to be replaced when shader is dynamically defined by its layout - vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" - "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n" - " initAttributes(input);\n"; + vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n"; + + // Write the HLSL input/output declarations + vertexStream << "struct VS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream); + vertexStream << "\n" + << "VS_OUTPUT main(VS_INPUT input)\n" + << "{\n" + << " initAttributes(input);\n"; if (vertexShader->usesDeferredInit()) { - vertexHLSL += "\n" - " initializeDeferredGlobals();\n"; + vertexStream << "\n" + << " initializeDeferredGlobals();\n"; } - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n"; + vertexStream << "\n" + << " gl_main();\n" + << "\n" + << " VS_OUTPUT output;\n"; + + const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX); - if (outputPositionFromVS) + if (vertexBuiltins.glPosition.enabled) { - vertexHLSL += " output.gl_Position = gl_Position;\n"; + vertexStream << " output.gl_Position = gl_Position;\n"; } // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. - if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { - vertexHLSL += " output.dx_Position.x = gl_Position.x;\n" - " output.dx_Position.y = -gl_Position.y;\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; + vertexStream << " output.dx_Position.x = gl_Position.x;\n" + << " output.dx_Position.y = -gl_Position.y;\n" + << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; } else { - vertexHLSL += " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" - " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; + vertexStream << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + " + "dx_ViewAdjust.x * gl_Position.w;\n" + << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + " + "dx_ViewAdjust.y * gl_Position.w);\n" + << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; } // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. - if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation) + if (vertexBuiltins.glPointSize.enabled) { - vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; + vertexStream << " output.gl_PointSize = gl_PointSize;\n"; } - if (usesFragCoord) + if (vertexBuiltins.glFragCoord.enabled) { - vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; + vertexStream << " output.gl_FragCoord = gl_Position;\n"; } - for (const PackedVarying &packedVarying : packedVaryings) + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) { - if (!packedVarying.registerAssigned()) - { - continue; - } + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isStruct()); - const sh::Varying &varying = *packedVarying.varying; + vertexStream << " output.v" << registerInfo.semanticIndex << " = "; - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) + if (packedVarying.isStructField()) { - int variableRows = - (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type))); - - for (int row = 0; row < variableRows; row++) - { - int r = packedVarying.registerIndex + - packedVarying.columnIndex * data.caps->maxVaryingVectors + - elementIndex * variableRows + row; - vertexHLSL += " output.v" + Str(r); - - vertexHLSL += " = _" + varying.name; + vertexStream << decorateVariable(packedVarying.parentStructName) << "."; + } - if (varying.isArray()) - { - vertexHLSL += ArrayString(elementIndex); - } + vertexStream << decorateVariable(varying.name); - if (variableRows > 1) - { - vertexHLSL += ArrayString(row); - } + if (varying.isArray()) + { + WriteArrayString(vertexStream, registerInfo.varyingArrayIndex); + } - vertexHLSL += ";\n"; - } + if (VariableRowCount(varying.type) > 1) + { + WriteArrayString(vertexStream, registerInfo.varyingRowIndex); } + + vertexStream << ";\n"; } // Instanced PointSprite emulation requires additional entries to calculate // the final output vertex positions of the quad that represents each sprite. if (useInstancedPointSpriteEmulation) { - vertexHLSL += "\n" - " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n" - " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n"; + vertexStream << "\n" + << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n" + << " output.dx_Position.xyz += float3(input.spriteVertexPos.x * " + "gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * " + "gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * " + "output.dx_Position.w;\n"; - if (usesPointCoord) + if (programMetadata.usesPointCoord()) { - vertexHLSL += "\n" - " output.gl_PointCoord = input.spriteTexCoord;\n"; + vertexStream << "\n" + << " output.gl_PointCoord = input.spriteTexCoord;\n"; } } - vertexHLSL += "\n" - " return output;\n" - "}\n"; - - const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord, - (!useInstancedPointSpriteEmulation && usesPointSize), true); - - pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; - - if (shaderVersion < 300) + // Renderers that enable instanced pointsprite emulation require the vertex shader output member + // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same + // default value used in the generated pixel shader. + if (programMetadata.usesInsertedPointCoordValue()) { - for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) - { - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = GL_FLOAT_VEC4; - outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); - outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; - outputKeyVariable.outputIndex = renderTargetIndex; - - outPixelShaderKey->push_back(outputKeyVariable); - } - - *outUsesFragDepth = fragmentShader->mUsesFragDepth; + ASSERT(!useInstancedPointSpriteEmulation); + vertexStream << "\n" + << " output.gl_PointCoord = float2(0.5, 0.5);\n"; } - else - { - const auto &shaderOutputVars = fragmentShaderGL->getActiveOutputVariables(); - - for (auto outputPair : programData.getOutputVariables()) - { - const VariableLocation &outputLocation = outputPair.second; - const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; - const std::string &variableName = "out_" + outputLocation.name; - const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); - ASSERT(outputVariable.staticUse); + vertexStream << "\n" + << " return output;\n" + << "}\n"; - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = outputVariable.type; - outputKeyVariable.name = variableName + elementString; - outputKeyVariable.source = variableName + ArrayString(outputLocation.element); - outputKeyVariable.outputIndex = outputPair.first; - - outPixelShaderKey->push_back(outputKeyVariable); - } - - *outUsesFragDepth = false; - } + std::stringstream pixelStream; + pixelStream << fragmentShaderGL->getTranslatedSource(); + pixelStream << "struct PS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream); + pixelStream << "\n"; - pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n"; + pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n"; - if (fragmentShader->mUsesFrontFacing) + if (fragmentShader->usesFrontFacing()) { if (shaderModel >= 4) { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" + << "{\n"; } else { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" + << "{\n"; } } else { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input)\n" + << "{\n"; } - if (usesFragCoord) + const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL); + + if (pixelBuiltins.glFragCoord.enabled) { - pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; + pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n"; // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. - // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords. + // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using + // dx_ViewCoords. if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" - " gl_FragCoord.y = input.dx_Position.y;\n"; + pixelStream << " gl_FragCoord.x = input.dx_Position.x;\n" + << " gl_FragCoord.y = input.dx_Position.y;\n"; } else if (shaderModel == 3) { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" - " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; + pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" + << " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; } else { - // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport() - pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n" - " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n"; + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See + // Renderer::setViewport() + pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + " + "dx_ViewCoords.z;\n" + << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + " + "dx_ViewCoords.w;\n"; } - pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" - " gl_FragCoord.w = rhw;\n"; + pixelStream << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + " + "dx_DepthFront.y;\n" + << " gl_FragCoord.w = rhw;\n"; } - if (usesPointCoord && shaderModel >= 3) + if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3) { - pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; - pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; + pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n" + << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; } - if (fragmentShader->mUsesFrontFacing) + if (fragmentShader->usesFrontFacing()) { if (shaderModel <= 3) { - pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; } else { - pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; + pixelStream << " gl_FrontFacing = isFrontFace;\n"; } } - for (const PackedVarying &packedVarying : packedVaryings) + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) { - const sh::Varying &varying = *packedVarying.varying; + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isBuiltIn() && !varying.isStruct()); - if (!packedVarying.registerAssigned()) - { - ASSERT(varying.isBuiltIn() || !varying.staticUse); + // Don't reference VS-only transform feedback varyings in the PS. + if (registerInfo.packedVarying->vertexOnly) continue; + + pixelStream << " "; + + if (packedVarying.isStructField()) + { + pixelStream << decorateVariable(packedVarying.parentStructName) << "."; } - // Don't reference VS-only transform feedback varyings in the PS. - if (packedVarying.vertexOnly) - continue; + pixelStream << decorateVariable(varying.name); - ASSERT(!varying.isBuiltIn()); - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) + if (varying.isArray()) { - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - for (int row = 0; row < variableRows; row++) - { - std::string n = Str(packedVarying.registerIndex + - packedVarying.columnIndex * data.caps->maxVaryingVectors + - elementIndex * variableRows + row); - pixelHLSL += " _" + varying.name; + WriteArrayString(pixelStream, registerInfo.varyingArrayIndex); + } - if (varying.isArray()) - { - pixelHLSL += ArrayString(elementIndex); - } + GLenum transposedType = TransposeMatrixType(varying.type); + if (VariableRowCount(transposedType) > 1) + { + WriteArrayString(pixelStream, registerInfo.varyingRowIndex); + } - if (variableRows > 1) - { - pixelHLSL += ArrayString(row); - } + pixelStream << " = input.v" << registerInfo.semanticIndex; - if (varying.isStruct()) - { - pixelHLSL += " = input.v" + n + ";\n"; - break; - } - else - { - switch (VariableColumnCount(transposedType)) - { - case 1: - pixelHLSL += " = input.v" + n + ".x;\n"; - break; - case 2: - pixelHLSL += " = input.v" + n + ".xy;\n"; - break; - case 3: - pixelHLSL += " = input.v" + n + ".xyz;\n"; - break; - case 4: - pixelHLSL += " = input.v" + n + ";\n"; - break; - default: - UNREACHABLE(); - } - } - } + switch (VariableColumnCount(transposedType)) + { + case 1: + pixelStream << ".x"; + break; + case 2: + pixelStream << ".xy"; + break; + case 3: + pixelStream << ".xyz"; + break; + case 4: + break; + default: + UNREACHABLE(); } + pixelStream << ";\n"; } if (fragmentShader->usesDeferredInit()) { - pixelHLSL += "\n" - " initializeDeferredGlobals();\n"; + pixelStream << "\n" + << " initializeDeferredGlobals();\n"; } - pixelHLSL += "\n" - " gl_main();\n" - "\n" - " return generateOutput();\n" - "}\n"; + pixelStream << "\n" + << " gl_main();\n" + << "\n" + << " return generateOutput();\n" + << "}\n"; + + *vertexHLSL = vertexStream.str(); + *pixelHLSL = pixelStream.str(); return true; } -std::string DynamicHLSL::generateGeometryShaderHLSL( - int registers, - const ShaderD3D *fragmentShader, - const std::vector<PackedVarying> &packedVaryings) const +std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const { - // for now we only handle point sprite emulation ASSERT(mRenderer->getMajorShaderModel() >= 4); - return generatePointSpriteHLSL(registers, fragmentShader, packedVaryings); + + std::stringstream preambleStream; + + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + + preambleStream << "struct GS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream); + preambleStream << "\n" + << "struct GS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream); + preambleStream + << "\n" + << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" + << "{\n" + << " output.gl_Position = input.gl_Position;\n"; + + if (builtins.glPointSize.enabled) + { + preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; + } + + for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList()) + { + preambleStream << " output.v" << varyingRegister.semanticIndex << " = "; + if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT) + { + preambleStream << "flat"; + } + preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n"; + } + + if (builtins.glFragCoord.enabled) + { + preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; + } + + // Only write the dx_Position if we aren't using point sprites + preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n" + << " output.dx_Position = input.dx_Position;\n" + << "#endif // ANGLE_POINT_SPRITE_SHADER\n" + << "}\n"; + + return preambleStream.str(); } -std::string DynamicHLSL::generatePointSpriteHLSL( - int registers, - const ShaderD3D *fragmentShader, - const std::vector<PackedVarying> &packedVaryings) const +std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::Data &data, + const gl::Program::Data &programData, + const std::string &preambleString) const { - ASSERT(registers >= 0); ASSERT(mRenderer->getMajorShaderModel() >= 4); - std::string geomHLSL; - - const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, - false, true, false); - const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, - fragmentShader->mUsesPointCoord, true, false); - - // If we're generating the geometry shader, we assume the vertex shader uses point size. - std::string varyingHLSL = generateVaryingHLSL(packedVaryings, true); - std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL); - std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL); - - // TODO(geofflang): use context's caps - geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" - "\n" - "struct GS_INPUT\n" + inLinkHLSL + "\n" + - "struct GS_OUTPUT\n" + outLinkHLSL + "\n" + - "\n" - "static float2 pointSpriteCorners[] = \n" - "{\n" - " float2( 0.5f, -0.5f),\n" - " float2( 0.5f, 0.5f),\n" - " float2(-0.5f, -0.5f),\n" - " float2(-0.5f, 0.5f)\n" - "};\n" - "\n" - "static float2 pointSpriteTexcoords[] = \n" - "{\n" - " float2(1.0f, 1.0f),\n" - " float2(1.0f, 0.0f),\n" - " float2(0.0f, 1.0f),\n" - " float2(0.0f, 0.0f)\n" - "};\n" - "\n" - "static float minPointSize = " + Str(static_cast<int>(mRenderer->getRendererCaps().minAliasedPointSize)) + ".0f;\n" - "static float maxPointSize = " + Str(static_cast<int>(mRenderer->getRendererCaps().maxAliasedPointSize)) + ".0f;\n" - "\n" - "[maxvertexcount(4)]\n" - "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n" - "{\n" - " GS_OUTPUT output = (GS_OUTPUT)0;\n" - " output.gl_Position = input[0].gl_Position;\n" - " output.gl_PointSize = input[0].gl_PointSize;\n"; - - for (int r = 0; r < registers; r++) + std::stringstream shaderStream; + + const bool pointSprites = (primitiveType == PRIMITIVE_POINTS); + const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos; + + const char *inputPT = nullptr; + const char *outputPT = nullptr; + int inputSize = 0; + int maxVertexOutput = 0; + + switch (primitiveType) + { + case PRIMITIVE_POINTS: + inputPT = "point"; + outputPT = "Triangle"; + inputSize = 1; + maxVertexOutput = 4; + break; + + case PRIMITIVE_LINES: + case PRIMITIVE_LINE_STRIP: + case PRIMITIVE_LINE_LOOP: + inputPT = "line"; + outputPT = "Line"; + inputSize = 2; + maxVertexOutput = 2; + break; + + case PRIMITIVE_TRIANGLES: + case PRIMITIVE_TRIANGLE_STRIP: + case PRIMITIVE_TRIANGLE_FAN: + inputPT = "triangle"; + outputPT = "Triangle"; + inputSize = 3; + maxVertexOutput = 3; + break; + + default: + UNREACHABLE(); + break; + } + + if (pointSprites) + { + shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" + "\n" + "uniform float4 dx_ViewCoords : register(c1);\n" + "\n" + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + << static_cast<int>(data.caps->minAliasedPointSize) + << ".0f;\n" + "static float maxPointSize = " + << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n" + << "\n"; + } + + shaderStream << preambleString << "\n" + << "[maxvertexcount(" << maxVertexOutput << ")]\n" + << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], "; + + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) + { + shaderStream << "uint primitiveID : SV_PrimitiveID, "; + } + + shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n" + << "{\n" + << " GS_OUTPUT output = (GS_OUTPUT)0;\n"; + + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) + { + shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n"; + } + else { - geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n"; + shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n"; } - if (fragmentShader->mUsesFragCoord) + for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex) { - geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; - } + shaderStream << " copyVertex(output, input[" << vertexIndex + << "], input[lastVertexIndex]);\n"; - geomHLSL += " \n" - " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" - " float4 dx_Position = input[0].dx_Position;\n" - " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_Position.w;\n"; + if (!pointSprites) + { + ASSERT(inputSize == maxVertexOutput); + shaderStream << " outStream.Append(output);\n"; + } + } - for (int corner = 0; corner < 4; corner++) + if (pointSprites) { - geomHLSL += " \n" - " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + shaderStream << "\n" + " float4 dx_Position = input[0].dx_Position;\n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, " + "maxPointSize);\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / " + "dx_ViewCoords.y) * dx_Position.w;\n"; - if (fragmentShader->mUsesPointCoord) + for (int corner = 0; corner < 4; corner++) { - geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n"; - } + shaderStream << "\n" + " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; - geomHLSL += " outStream.Append(output);\n"; + if (usesPointCoord) + { + shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner + << "];\n"; + } + + shaderStream << " outStream.Append(output);\n"; + } } - geomHLSL += " \n" - " outStream.RestartStrip();\n" - "}\n"; + shaderStream << " \n" + " outStream.RestartStrip();\n" + "}\n"; - return geomHLSL; + return shaderStream.str(); } // This method needs to match OutputHLSL::decorate @@ -1232,11 +902,12 @@ std::string DynamicHLSL::decorateVariable(const std::string &name) return name; } -std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, - const sh::ShaderVariable &shaderAttrib) const +std::string DynamicHLSL::generateAttributeConversionHLSL( + gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib) const { const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); - std::string attribString = "input." + decorateVariable(shaderAttrib.name); + std::string attribString = "input." + decorateVariable(shaderAttrib.name); // Matrix if (IsMatrixType(shaderAttrib.type)) @@ -1245,10 +916,11 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType ve } GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); - int shaderComponentCount = VariableComponentCount(shaderAttrib.type); + int shaderComponentCount = VariableComponentCount(shaderAttrib.type); // Perform integer to float conversion (if necessary) - bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT); + bool requiresTypeConversion = + (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT); if (requiresTypeConversion) { @@ -1261,4 +933,57 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType ve return attribString; } +void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &metadata, + std::vector<PixelShaderOutputVariable> *outPixelShaderKey) +{ + // Two cases when writing to gl_FragColor and using ESSL 1.0: + // - with a 3.0 context, the output color is copied to channel 0 + // - with a 2.0 context, the output color is broadcast to all channels + bool broadcast = metadata.usesBroadcast(data); + const unsigned int numRenderTargets = + (broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1); + + if (metadata.getMajorShaderVersion() < 300) + { + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; + renderTargetIndex++) + { + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = GL_FLOAT_VEC4; + outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); + outputKeyVariable.source = + broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; + outputKeyVariable.outputIndex = renderTargetIndex; + + outPixelShaderKey->push_back(outputKeyVariable); + } + } + else + { + const auto &shaderOutputVars = + metadata.getFragmentShader()->getData().getActiveOutputVariables(); + + for (auto outputPair : programData.getOutputVariables()) + { + const VariableLocation &outputLocation = outputPair.second; + const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const std::string &variableName = "out_" + outputLocation.name; + const std::string &elementString = + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); + + ASSERT(outputVariable.staticUse); + + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = outputVariable.type; + outputKeyVariable.name = variableName + elementString; + outputKeyVariable.source = variableName + ArrayString(outputLocation.element); + outputKeyVariable.outputIndex = outputPair.first; + + outPixelShaderKey->push_back(outputKeyVariable); + } + } } + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h index 45290339207..df52d245cfc 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -17,6 +17,7 @@ #include "libANGLE/Constants.h" #include "libANGLE/Program.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace sh { @@ -28,15 +29,16 @@ namespace gl { class InfoLog; struct VariableLocation; -struct LinkedVarying; struct VertexAttribute; struct Data; } namespace rx { -class RendererD3D; +struct PackedVarying; +class ProgramD3DMetadata; class ShaderD3D; +class VaryingPacking; struct PixelShaderOutputVariable { @@ -46,75 +48,47 @@ struct PixelShaderOutputVariable size_t outputIndex; }; -struct PackedVarying -{ - PackedVarying(const sh::Varying &varyingIn) - : varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0), vertexOnly(false) - { - } - - bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } - - void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; } - - const sh::Varying *varying; - - // Assigned during link - unsigned int registerIndex; - - // Assigned during link, Defaults to 0 - unsigned int columnIndex; - - // Transform feedback varyings can be only referenced in the VS. - bool vertexOnly; -}; - class DynamicHLSL : angle::NonCopyable { public: explicit DynamicHLSL(RendererD3D *const renderer); - int packVaryings(gl::InfoLog &infoLog, - std::vector<PackedVarying> *packedVaryings, - const std::vector<std::string> &transformFeedbackVaryings); - std::string generateVertexShaderForInputLayout(const std::string &sourceShader, - const gl::InputLayout &inputLayout, - const std::vector<sh::Attribute> &shaderAttributes) const; - std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables, - bool usesFragDepth, const std::vector<GLenum> &outputLayout) const; + std::string generateVertexShaderForInputLayout( + const std::string &sourceShader, + const gl::InputLayout &inputLayout, + const std::vector<sh::Attribute> &shaderAttributes) const; + std::string generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector<PixelShaderOutputVariable> &outputVariables, + bool usesFragDepth, + const std::vector<GLenum> &outputLayout) const; bool generateShaderLinkHLSL(const gl::Data &data, const gl::Program::Data &programData, - gl::InfoLog &infoLog, - int registers, - std::string &pixelHLSL, - std::string &vertexHLSL, - const std::vector<PackedVarying> &packedVaryings, - std::vector<gl::LinkedVarying> *linkedVaryings, - std::vector<PixelShaderOutputVariable> *outPixelShaderKey, - bool *outUsesFragDepth) const; - - std::string generateGeometryShaderHLSL(int registers, - const ShaderD3D *fragmentShader, - const std::vector<PackedVarying> &packedVaryings) const; + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const; + + std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const; + + std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::Data &data, + const gl::Program::Data &programData, + const std::string &preambleString) const; + + void getPixelShaderOutputKey(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &metadata, + std::vector<PixelShaderOutputVariable> *outPixelShaderKey); private: RendererD3D *const mRenderer; - struct SemanticInfo; - - std::string getVaryingSemantic(bool pointSize) const; - SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord, - bool pointSize, bool pixelShader) const; - std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; - std::string generateVaryingHLSL(const std::vector<PackedVarying> &varyings, - bool shaderUsesPointSize) const; - void storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings, - bool shaderUsesPointSize, - std::vector<gl::LinkedVarying> *linkedVaryings) const; - void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const; - std::string generatePointSpriteHLSL(int registers, - const ShaderD3D *fragmentShader, - const std::vector<PackedVarying> &packedVaryings) const; + 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); @@ -123,6 +97,7 @@ class DynamicHLSL : angle::NonCopyable const sh::ShaderVariable &shaderAttrib) const; }; +std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize); } -#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ +#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp deleted file mode 100644 index ea7a331812d..00000000000 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp +++ /dev/null @@ -1,30 +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. -// -// DynamicHLSL unittests: -// Tests for DynamicHLSL and related classes. -// - -#include <gtest/gtest.h> - -#include "libANGLE/renderer/d3d/DynamicHLSL.h" - -using namespace rx; - -namespace -{ - -TEST(PackedVarying, DefaultInitialization) -{ - sh::Varying defaultVarying; - PackedVarying pv(defaultVarying); - - EXPECT_EQ(&defaultVarying, pv.varying); - EXPECT_EQ(GL_INVALID_INDEX, pv.registerIndex); - EXPECT_EQ(0, pv.columnIndex); - EXPECT_FALSE(pv.vertexOnly); -} - -} // anonymous namespace diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp index b5cc1beeb35..5be3c16faf6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -125,13 +125,16 @@ gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) { const gl::State &state = *data.state; ClearParameters clearParams = GetClearParameters(state, mask); - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) { // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); if (buffer == GL_COLOR) { @@ -149,13 +152,16 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, G clearParams.depthClearValue = values[0]; } - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) { // glClearBufferuiv can only be called to clear a color buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); @@ -163,13 +169,16 @@ gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) { // glClearBufferiv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); if (buffer == GL_COLOR) { @@ -187,19 +196,23 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, G clearParams.stencilClearValue = values[1]; } - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) { // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); clearParams.clearDepth = true; clearParams.depthClearValue = depth; clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - return clear(state, clearParams); + return clear(data, clearParams); } GLenum FramebufferD3D::getImplementationColorReadFormat() const @@ -250,17 +263,15 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle { const gl::PixelPackState &packState = state.getPackState(); - if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); - } - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); + GLuint outputPitch = + sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength); + GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels( + outputPitch, 0, 0, packState.skipRows, packState.skipPixels); - return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels)); + 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, @@ -304,14 +315,14 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour return gl::Error(GL_NO_ERROR); } -GLenum FramebufferD3D::checkStatus() const +bool FramebufferD3D::checkStatus() const { // if we have both a depth and stencil buffer, they must refer to the same object // since we only support packed_depth_stencil and not separate depth and stencil if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr && mData.getDepthStencilAttachment() == nullptr) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return false; } // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness @@ -328,13 +339,19 @@ GLenum FramebufferD3D::checkStatus() const (attachment.id() == prevAttachment.id() && attachment.type() == prevAttachment.type())) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return false; } } } } - return GL_FRAMEBUFFER_COMPLETE; + // D3D requires all render targets to have the same dimensions. + if (!mData.attachmentsHaveSameDimensions()) + { + return false; + } + + return true; } const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender( diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h index 42f76ff3a3d..6b98cee7e7e 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -67,10 +67,23 @@ class FramebufferD3D : public FramebufferImpl void setReadBuffer(GLenum buffer) override; gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + gl::Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) override; + gl::Error clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) override; + gl::Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) override; GLenum getImplementationColorReadFormat() const override; GLenum getImplementationColorReadType() const override; @@ -79,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; - GLenum checkStatus() const override; + bool checkStatus() const override; const gl::AttachmentList &getColorAttachmentsForRender(const WorkaroundsD3D &workarounds) const; @@ -89,10 +102,14 @@ class FramebufferD3D : public FramebufferImpl mutable bool mInvalidateColorAttachmentCache; private: - virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0; - - virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const = 0; + virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0; + + virtual gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const = 0; virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index 7559b94b6ac..e8b1af31291 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -12,12 +12,9 @@ #include "libANGLE/histogram_macros.h" #include "third_party/trace_event/trace_event.h" -// Definitions local to the translation unit +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED namespace { - -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - #ifdef CREATE_COMPILER_FLAG_INFO #undef CREATE_COMPILER_FLAG_INFO #endif @@ -78,10 +75,8 @@ bool IsCompilerFlagSet(UINT mask, UINT flag) return isFlagSet; } } - -#endif - -} +} // anonymous namespace +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED namespace rx { @@ -247,8 +242,9 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string { *outCompiledBlob = binary; -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; + +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) @@ -279,7 +275,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string return error; } (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n"; -#endif +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED return gl::Error(GL_NO_ERROR); } @@ -289,7 +285,8 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); } - infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags."; + infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. (" + << profile << ")"; if (i + 1 < configs.size()) { @@ -332,4 +329,4 @@ gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *d return gl::Error(GL_NO_ERROR); } -} +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp index 19cdbec7249..c18ffe1639b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -18,57 +18,82 @@ namespace rx { -static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, - GLsizei count, void *output) +namespace { - if (sourceType == GL_UNSIGNED_BYTE) - { - ASSERT(destinationType == GL_UNSIGNED_SHORT); - const GLubyte *in = static_cast<const GLubyte*>(input); - GLushort *out = static_cast<GLushort*>(output); +template <typename InputT, typename DestT> +void ConvertIndexArray(const void *input, + GLenum sourceType, + void *output, + GLenum destinationType, + GLsizei count, + bool usePrimitiveRestartFixedIndex) +{ + const InputT *in = static_cast<const InputT *>(input); + DestT *out = static_cast<DestT *>(output); + + if (usePrimitiveRestartFixedIndex) + { + InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType)); + DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType)); for (GLsizei i = 0; i < count; i++) { - out[i] = in[i]; + out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i])); } } - else if (sourceType == GL_UNSIGNED_INT) - { - ASSERT(destinationType == GL_UNSIGNED_INT); - memcpy(output, input, count * sizeof(GLuint)); - } - else if (sourceType == GL_UNSIGNED_SHORT) + else { - if (destinationType == GL_UNSIGNED_SHORT) + for (GLsizei i = 0; i < count; i++) { - memcpy(output, input, count * sizeof(GLushort)); + out[i] = static_cast<DestT>(in[i]); } - else if (destinationType == GL_UNSIGNED_INT) - { - const GLushort *in = static_cast<const GLushort*>(input); - GLuint *out = static_cast<GLuint*>(output); + } +} - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else UNREACHABLE(); +void ConvertIndices(GLenum sourceType, + GLenum destinationType, + const void *input, + GLsizei count, + void *output, + bool usePrimitiveRestartFixedIndex) +{ + if (sourceType == destinationType) + { + const gl::Type &typeInfo = gl::GetTypeInfo(destinationType); + memcpy(output, input, count * typeInfo.bytes); + return; + } + + if (sourceType == GL_UNSIGNED_BYTE) + { + ASSERT(destinationType == GL_UNSIGNED_SHORT); + ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); + } + else if (sourceType == GL_UNSIGNED_SHORT) + { + ASSERT(destinationType == GL_UNSIGNED_INT); + ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); } else UNREACHABLE(); } -static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid *data, - unsigned int count, GLenum srcType, GLenum dstType, - unsigned int *offset) +gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, + const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + unsigned int *offset) { const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift)) { return gl::Error(GL_OUT_OF_MEMORY, - "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", - count, dstTypeInfo.bytes); + "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", + count, dstTypeInfo.bytes); } unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift; @@ -85,7 +110,7 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid return error; } - ConvertIndices(srcType, dstType, data, count, output); + ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex); error = buffer->unmapBuffer(); if (error.isError()) @@ -96,6 +121,8 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid return gl::Error(GL_NO_ERROR); } +} // anonymous namespace + IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) : mFactory(factory), mRendererClass(rendererClass), @@ -118,9 +145,13 @@ IndexDataManager::~IndexDataManager() // When we have a buffer with an unsupported format (subcase b) then we need to do some translation: // we will start by falling back to streaming, and after a while will start using a static translated // copy of the index buffer. -gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer, - const GLvoid *indices, TranslatedIndexData *translated, - SourceIndexData *sourceData) +gl::Error IndexDataManager::prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + SourceIndexData *sourceData, + bool primitiveRestartFixedIndexEnabled) { // Avoid D3D11's primitive restart index value // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx @@ -128,8 +159,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: 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; @@ -151,7 +188,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: if (glBuffer == nullptr) { translated->storage = nullptr; - return streamIndexData(indices, count, srcType, dstType, translated); + return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled, + translated); } // Case 2: the indices are already in a buffer @@ -193,7 +231,7 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: if (staticBufferInitialized && !staticBufferUsable) { - buffer->invalidateStaticData(); + buffer->invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); staticBuffer = nullptr; } @@ -207,7 +245,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: } ASSERT(bufferData != nullptr); - error = streamIndexData(bufferData + offset, count, srcType, dstType, translated); + error = streamIndexData(bufferData + offset, count, srcType, dstType, + primitiveRestartFixedIndexEnabled, translated); if (error.isError()) { return error; @@ -227,8 +266,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: unsigned int convertCount = static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift; - error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, - srcType, dstType, nullptr); + error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType, + primitiveRestartFixedIndexEnabled, nullptr); if (error.isError()) { return error; @@ -245,8 +284,12 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: return gl::Error(GL_NO_ERROR); } -gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType, - GLenum dstType, TranslatedIndexData *translated) +gl::Error IndexDataManager::streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated) { const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); @@ -259,7 +302,8 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int cou ASSERT(indexBuffer != nullptr); unsigned int offset; - StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, &offset); + StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex, + &offset); translated->indexBuffer = indexBuffer->getIndexBuffer(); translated->serial = indexBuffer->getSerial(); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h index cd9c8b7110f..c3741cfe3fc 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -63,13 +63,21 @@ class IndexDataManager : angle::NonCopyable explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); virtual ~IndexDataManager(); - gl::Error prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer, - const GLvoid *indices, TranslatedIndexData *translated, - SourceIndexData *sourceData); + gl::Error prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + SourceIndexData *sourceData, + bool primitiveRestartFixedIndexEnabled); private: - gl::Error streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType, - GLenum dstType, TranslatedIndexData *translated); + gl::Error streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated); gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp index 0a182ae9543..7f44d585a30 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -20,6 +20,7 @@ #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h" #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/VaryingPacking.h" #include "libANGLE/renderer/d3d/VertexDataManager.h" namespace rx @@ -38,14 +39,13 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); for (size_t rowIndex = 0; - static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); - ++rowIndex) + static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex) { GLenum componentType = gl::VariableComponentType(transposedType); - GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType)); + GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType)); bool pureInt = (componentType != GL_FLOAT); - gl::VertexFormatType defaultType = gl::GetVertexFormatType( - componentType, GL_FALSE, components, pureInt); + gl::VertexFormatType defaultType = + gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt); defaultLayout.push_back(defaultType); } @@ -55,7 +55,8 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) return defaultLayout; } -std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars) +std::vector<GLenum> GetDefaultOutputLayoutFromShader( + const std::vector<PixelShaderOutputVariable> &shaderOutputVars) { std::vector<GLenum> defaultPixelOutput; @@ -90,14 +91,22 @@ struct AttributeSorter int indexA = (*originalIndices)[a]; int indexB = (*originalIndices)[b]; - if (indexA == -1) return false; - if (indexB == -1) return true; + if (indexA == -1) + return false; + if (indexB == -1) + return true; return (indexA < indexB); } 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); +} + std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, const gl::Shader &fragmentShader, const std::vector<std::string> &tfVaryings) @@ -118,7 +127,20 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, { if (output.name == input.name) { - packedVaryings.push_back(PackedVarying(input)); + 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; } @@ -131,14 +153,22 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, { if (tfVarying == output.name) { - packedVaryings.push_back(PackedVarying(output)); - packedVaryings.back().vertexOnly = true; + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (!output.isStruct()) + { + packedVaryings.push_back(PackedVarying(output, output.interpolation)); + packedVaryings.back().vertexOnly = true; + } break; } } } } + std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying); + return packedVaryings; } @@ -178,8 +208,129 @@ void GetUniformBlockInfo(const std::vector<VarT> &fields, } } +template <typename T> +static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); + + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template <typename T> +bool TransposeMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); + + for (int x = 0; x < copyWidth; x++) + { + for (int y = 0; y < copyHeight; y++) + { + SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) + { + for (int x = copyHeight; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + + return dirty; +} + +template <typename T> +bool ExpandMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetWidth, srcWidth); + int copyHeight = std::min(targetHeight, srcHeight); + + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyHeight; y++) + { + for (int x = copyWidth; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyHeight; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); + } + } + + return dirty; +} + +gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode) +{ + switch (drawMode) + { + // Uses the point sprite geometry shader. + case GL_POINTS: + return gl::PRIMITIVE_POINTS; + + // All line drawing uses the same geometry shader. + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + return gl::PRIMITIVE_LINES; + + // The triangle fan primitive is emulated with strips in D3D11. + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + return gl::PRIMITIVE_TRIANGLES; + + // Special case for triangle strips. + case GL_TRIANGLE_STRIP: + return gl::PRIMITIVE_TRIANGLE_STRIP; + + default: + UNREACHABLE(); + return gl::PRIMITIVE_TYPE_MAX; + } +} + } // anonymous namespace +// D3DUniform Implementation + D3DUniform::D3DUniform(GLenum typeIn, const std::string &nameIn, unsigned int arraySizeIn, @@ -228,12 +379,120 @@ bool D3DUniform::isReferencedByFragmentShader() const return psRegisterIndex != GL_INVALID_INDEX; } +// D3DVarying Implementation + +D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) +{ +} + +D3DVarying::D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn) + : semanticName(semanticNameIn), + semanticIndex(semanticIndexIn), + componentCount(componentCountIn), + outputSlot(outputSlotIn) +{ +} + +// ProgramD3DMetadata Implementation + +ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel, + const std::string &shaderModelSuffix, + bool usesInstancedPointSpriteEmulation, + const ShaderD3D *vertexShader, + const ShaderD3D *fragmentShader) + : mRendererMajorShaderModel(rendererMajorShaderModel), + mShaderModelSuffix(shaderModelSuffix), + mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation), + mVertexShader(vertexShader), + mFragmentShader(fragmentShader) +{ +} + +int ProgramD3DMetadata::getRendererMajorShaderModel() const +{ + return mRendererMajorShaderModel; +} + +bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const +{ + return (mFragmentShader->usesFragColor() && data.clientVersion < 3); +} + +bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const +{ + return mFragmentShader->usesFragDepth(); +} + +bool ProgramD3DMetadata::usesPointCoord() const +{ + return mFragmentShader->usesPointCoord(); +} + +bool ProgramD3DMetadata::usesFragCoord() const +{ + return mFragmentShader->usesFragCoord(); +} + +bool ProgramD3DMetadata::usesPointSize() const +{ + return mVertexShader->usesPointSize(); +} + +bool ProgramD3DMetadata::usesInsertedPointCoordValue() const +{ + return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4; +} + +bool ProgramD3DMetadata::addsPointCoordToVertexShader() const +{ + // Instanced PointSprite emulation requires 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. + return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) || + usesInsertedPointCoordValue(); +} + +bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const +{ + // gl_Position only needs to be outputted from the vertex shader if transform feedback is + // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from + // the vertex shader in this case. This saves us 1 output vector. + return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != ""); +} + +bool ProgramD3DMetadata::usesSystemValuePointSize() const +{ + return !mUsesInstancedPointSpriteEmulation && usesPointSize(); +} + +bool ProgramD3DMetadata::usesMultipleFragmentOuts() const +{ + return mFragmentShader->usesMultipleRenderTargets(); +} + +GLint ProgramD3DMetadata::getMajorShaderVersion() const +{ + return mVertexShader->getData().getShaderVersion(); +} + +const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const +{ + return mFragmentShader; +} + +// ProgramD3D Implementation + ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout, const Signature &signature, ShaderExecutableD3D *shaderExecutable) - : mInputs(inputLayout), - mSignature(signature), - mShaderExecutable(shaderExecutable) + : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable) { } @@ -281,8 +540,7 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable) - : mOutputSignature(outputSignature), - mShaderExecutable(shaderExecutable) + : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable) { } @@ -301,8 +559,9 @@ ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer) : ProgramImpl(data), mRenderer(renderer), mDynamicHLSL(NULL), - mGeometryExecutable(NULL), + mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr), mUsesPointSize(false), + mUsesFlatInterpolation(false), mVertexUniformStorage(NULL), mFragmentUniformStorage(NULL), mUsedVertexSamplerRange(0), @@ -324,8 +583,13 @@ bool ProgramD3D::usesPointSpriteEmulation() const return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; } -bool ProgramD3D::usesGeometryShader() const +bool ProgramD3D::usesGeometryShader(GLenum drawMode) const { + if (drawMode != GL_POINTS) + { + return mUsesFlatInterpolation; + } + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); } @@ -334,30 +598,34 @@ bool ProgramD3D::usesInstancedPointSpriteEmulation() const return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; } -GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const +GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, + unsigned int samplerIndex, + const gl::Caps &caps) const { GLint logicalTextureUnit = -1; switch (type) { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < caps.maxTextureImageUnits); - if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) - { - logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; - } - break; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); - if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) - { - logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; - } - break; - default: UNREACHABLE(); + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: + UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) + if (logicalTextureUnit >= 0 && + logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -371,15 +639,16 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp { switch (type) { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < mSamplersPS.size()); - ASSERT(mSamplersPS[samplerIndex].active); - return mSamplersPS[samplerIndex].textureType; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < mSamplersVS.size()); - ASSERT(mSamplersVS[samplerIndex].active); - return mSamplersVS[samplerIndex].textureType; - default: UNREACHABLE(); + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < mSamplersPS.size()); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < mSamplersVS.size()); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: + UNREACHABLE(); } return GL_TEXTURE_2D; @@ -389,13 +658,13 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const { switch (type) { - case gl::SAMPLER_PIXEL: - return mUsedPixelSamplerRange; - case gl::SAMPLER_VERTEX: - return mUsedVertexSamplerRange; - default: - UNREACHABLE(); - return 0; + case gl::SAMPLER_PIXEL: + return mUsedPixelSamplerRange; + case gl::SAMPLER_VERTEX: + return mUsedVertexSamplerRange; + default: + UNREACHABLE(); + return 0; } } @@ -458,8 +727,9 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) { reset(); - DeviceIdentifier binaryDeviceIdentifier = { 0 }; - stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier)); + DeviceIdentifier binaryDeviceIdentifier = {0}; + stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier), + sizeof(DeviceIdentifier)); DeviceIdentifier identifier = mRenderer->getAdapterIdentifier(); if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0) @@ -527,30 +797,48 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) mD3DUniforms.push_back(d3dUniform); } - const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>(); - mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); - for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) + const unsigned int blockCount = stream->readInt<unsigned int>(); + if (stream->error()) + { + infoLog << "Invalid program binary."; + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + ASSERT(mD3DUniformBlocks.empty()); + for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + D3DUniformBlock uniformBlock; + stream->readInt(&uniformBlock.psRegisterIndex); + stream->readInt(&uniformBlock.vsRegisterIndex); + mD3DUniformBlocks.push_back(uniformBlock); + } + + const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>(); + mStreamOutVaryings.resize(streamOutVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex) { - gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; + D3DVarying *varying = &mStreamOutVaryings[varyingIndex]; - stream->readString(&varying.name); - stream->readInt(&varying.type); - stream->readInt(&varying.size); - stream->readString(&varying.semanticName); - stream->readInt(&varying.semanticIndex); - stream->readInt(&varying.semanticIndexCount); + stream->readString(&varying->semanticName); + stream->readInt(&varying->semanticIndex); + stream->readInt(&varying->componentCount); + stream->readInt(&varying->outputSlot); } stream->readString(&mVertexHLSL); - stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->readString(&mPixelHLSL); - stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->readBool(&mUsesFragDepth); stream->readBool(&mUsesPointSize); + stream->readBool(&mUsesFlatInterpolation); const size_t pixelShaderKeySize = stream->readInt<unsigned int>(); mPixelShaderKey.resize(pixelShaderKeySize); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; + pixelShaderKeyIndex++) { stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); @@ -558,10 +846,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); } - const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data()); + stream->readString(&mGeometryShaderPreamble); + + const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data()); const unsigned int vertexShaderCount = stream->readInt<unsigned int>(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; + vertexShaderIndex++) { size_t inputLayoutSize = stream->readInt<size_t>(); gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID); @@ -571,13 +862,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>(); } - unsigned int vertexShaderSize = stream->readInt<unsigned int>(); + unsigned int vertexShaderSize = stream->readInt<unsigned int>(); const unsigned char *vertexShaderFunction = binary + stream->offset(); ShaderExecutableD3D *shaderExecutable = nullptr; gl::Error error = mRenderer->loadExecutable( - vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings, + vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); if (error.isError()) { @@ -595,7 +886,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( + new VertexExecutable(inputLayout, signature, shaderExecutable)); stream->skip(vertexShaderSize); } @@ -610,12 +902,12 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readInt(&outputs[outputIndex]); } - const size_t pixelShaderSize = stream->readInt<unsigned int>(); + const size_t pixelShaderSize = stream->readInt<unsigned int>(); const unsigned char *pixelShaderFunction = binary + stream->offset(); ShaderExecutableD3D *shaderExecutable = nullptr; gl::Error error = mRenderer->loadExecutable( - pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings, + pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); if (error.isError()) { @@ -634,21 +926,28 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->skip(pixelShaderSize); } - unsigned int geometryShaderSize = stream->readInt<unsigned int>(); - - if (geometryShaderSize > 0) + for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX; + ++geometryExeIndex) { + unsigned int geometryShaderSize = stream->readInt<unsigned int>(); + if (geometryShaderSize == 0) + { + mGeometryExecutables[geometryExeIndex] = nullptr; + continue; + } + const unsigned char *geometryShaderFunction = binary + stream->offset(); - gl::Error error = mRenderer->loadExecutable( - geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable); + 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); } - if (!mGeometryExecutable) + if (!mGeometryExecutables[geometryExeIndex]) { infoLog << "Could not create geometry shader."; return LinkResult(false, gl::Error(GL_NO_ERROR)); @@ -665,9 +964,11 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) { // Output the DeviceIdentifier before we output any shader code - // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL + // When we load the binary again later, we can validate the device identifier before trying to + // compile any HLSL DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier(); - stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier)); + stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier), + sizeof(DeviceIdentifier)); stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); @@ -697,40 +998,45 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(mUsedPixelSamplerRange); stream->writeInt(mD3DUniforms.size()); - for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex) + for (const D3DUniform *uniform : mD3DUniforms) { - const D3DUniform &uniform = *mD3DUniforms[uniformIndex]; - // Type, name and arraySize are redundant, so aren't stored in the binary. - stream->writeInt(uniform.psRegisterIndex); - stream->writeInt(uniform.vsRegisterIndex); - stream->writeInt(uniform.registerCount); - stream->writeInt(uniform.registerElement); + stream->writeInt(uniform->psRegisterIndex); + stream->writeInt(uniform->vsRegisterIndex); + stream->writeInt(uniform->registerCount); + stream->writeInt(uniform->registerElement); } - stream->writeInt(mTransformFeedbackLinkedVaryings.size()); - for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) + stream->writeInt(mD3DUniformBlocks.size()); + for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks) { - const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; + stream->writeInt(uniformBlock.psRegisterIndex); + stream->writeInt(uniformBlock.vsRegisterIndex); + } - stream->writeString(varying.name); - stream->writeInt(varying.type); - stream->writeInt(varying.size); + stream->writeInt(mStreamOutVaryings.size()); + for (const auto &varying : mStreamOutVaryings) + { stream->writeString(varying.semanticName); stream->writeInt(varying.semanticIndex); - stream->writeInt(varying.semanticIndexCount); + stream->writeInt(varying.componentCount); + stream->writeInt(varying.outputSlot); } stream->writeString(mVertexHLSL); - stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->writeString(mPixelHLSL); - stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->writeInt(mUsesFragDepth); stream->writeInt(mUsesPointSize); + stream->writeInt(mUsesFlatInterpolation); const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey; stream->writeInt(pixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); + pixelShaderKeyIndex++) { const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; stream->writeInt(variable.type); @@ -739,8 +1045,11 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(variable.outputIndex); } + stream->writeString(mGeometryShaderPreamble); + stream->writeInt(mVertexExecutables.size()); - for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); + vertexExecutableIndex++) { VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; @@ -760,7 +1069,8 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) } stream->writeInt(mPixelExecutables.size()); - for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); + pixelExecutableIndex++) { PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; @@ -778,24 +1088,34 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeBytes(pixelBlob, pixelShaderSize); } - size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream->writeInt(geometryShaderSize); - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) + for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables) { - const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); - stream->writeBytes(geometryBlob, geometryShaderSize); + if (geometryExe == nullptr) + { + stream->writeInt(0); + continue; + } + + size_t geometryShaderSize = geometryExe->getLength(); + stream->writeInt(geometryShaderSize); + stream->writeBytes(geometryExe->getFunction(), geometryShaderSize); } return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable) +void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) +{ +} + +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExecutable) { mPixelShaderOutputFormatCache.clear(); const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo); - const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); + const gl::AttachmentList &colorbuffers = + fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -803,7 +1123,9 @@ gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fb if (colorbuffer) { - mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); + mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK + ? GL_COLOR_ATTACHMENT0 + : colorbuffer->getBinding()); } else { @@ -827,8 +1149,8 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum } } - std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature( + mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature); // Generate new pixel executable ShaderExecutableD3D *pixelExecutable = NULL; @@ -837,7 +1159,7 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; gl::Error error = mRenderer->compileToExecutable( - *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings, + *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, &pixelExecutable); if (error.isError()) @@ -886,7 +1208,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; gl::Error error = mRenderer->compileToExecutable( - *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings, + *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, &vertexExecutable); if (error.isError()) @@ -896,7 +1218,8 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i if (vertexExecutable) { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)); + mVertexExecutables.push_back( + new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)); } else if (!infoLog) { @@ -909,53 +1232,96 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i return gl::Error(GL_NO_ERROR); } -LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, - int registers, - const std::vector<PackedVarying> &packedVaryings) +gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog) { - const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader()); + if (outExecutable) + { + *outExecutable = nullptr; + } + + // We only uses a geometry shader for point sprite emulation, or for fixing the provoking + // vertex problem. Otherwise, return a null shader. + if (drawMode != GL_POINTS && !mUsesFlatInterpolation) + { + return gl::Error(GL_NO_ERROR); + } + + gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode); + + if (mGeometryExecutables[geometryShaderType] != nullptr) + { + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return gl::Error(GL_NO_ERROR); + } + + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL( + geometryShaderType, data, mData, 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]); + + if (!infoLog && error.isError()) + { + std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]); + } + + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return error; +} +LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog) +{ const gl::InputLayout &defaultInputLayout = GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader()); ShaderExecutableD3D *defaultVertexExecutable = NULL; - gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); + gl::Error error = + getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); if (error.isError()) { return LinkResult(false, error); } - std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); + std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); ShaderExecutableD3D *defaultPixelExecutable = NULL; - error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); + error = + getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); if (error.isError()) { return LinkResult(false, error); } - if (usesGeometryShader()) + // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11. + ShaderExecutableD3D *pointGS = nullptr; + if (usesGeometryShader(GL_POINTS)) { - std::string geometryHLSL = - mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings); - - error = mRenderer->compileToExecutable( - infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), - D3DCompilerWorkarounds(), &mGeometryExecutable); - if (error.isError()) - { - return LinkResult(false, error); - } + getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog); } -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader()); - if (usesGeometryShader() && mGeometryExecutable) + if (usesGeometryShader(GL_POINTS) && pointGS) { - // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level - // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch + // Geometry shaders are currently only used internally, so there is no corresponding shader + // object at the interface level. For now the geometry shader debug info is prepended to + // the vertex shader. vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); - vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo()); + vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo()); vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); } @@ -966,11 +1332,13 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, if (defaultPixelExecutable) { + const ShaderD3D *fragmentShaderD3D = + GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader()); fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); } -#endif - bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); + bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && + (!usesGeometryShader(GL_POINTS) || pointGS)); return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); } @@ -997,10 +1365,7 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); mSamplersPS.resize(data.caps->maxTextureImageUnits); - mVertexHLSL = vertexShader->getTranslatedSource(); vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); - - mPixelHLSL = fragmentShader->getTranslatedSource(); fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); if (mRenderer->getRendererLimitations().noFrontFacingSupport) @@ -1016,37 +1381,78 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames()); // Map the varyings to the register file - int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings, - mData.getTransformFeedbackVaryingNames()); + VaryingPacking varyingPacking(data.caps->maxVaryingVectors); + if (!varyingPacking.packVaryings(infoLog, packedVaryings, + mData.getTransformFeedbackVaryingNames())) + { + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(), + usesInstancedPointSpriteEmulation(), vertexShaderD3D, + fragmentShaderD3D); + + varyingPacking.enableBuiltins(SHADER_VERTEX, metadata); + varyingPacking.enableBuiltins(SHADER_PIXEL, metadata); - if (registers < 0) + 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)); } - std::vector<gl::LinkedVarying> linkedVaryings; - if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL, - mVertexHLSL, packedVaryings, &linkedVaryings, - &mPixelShaderKey, &mUsesFragDepth)) + // 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)); + } + + if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL, + &mVertexHLSL)) { return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUsesPointSize = vertexShaderD3D->usesPointSize(); + mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey); + mUsesFragDepth = metadata.usesFragDepth(mData); + + // Cache if we use flat shading + mUsesFlatInterpolation = false; + for (const auto &varying : packedVaryings) + { + if (varying.interpolation == sh::INTERPOLATION_FLAT) + { + mUsesFlatInterpolation = true; + break; + } + } + + if (mRenderer->getMajorShaderModel() >= 4) + { + varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata); + mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking); + } initSemanticIndex(); defineUniformsAndAssignRegisters(); - gatherTransformFeedbackVaryings(linkedVaryings); + gatherTransformFeedbackVaryings(varyingPacking); - LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings); + LinkResult result = compileProgramExecutables(data, infoLog); if (result.error.isError() || !result.linkSuccess) { infoLog << "Failed to create D3D shaders."; return result; } + initUniformBlockInfo(); + return LinkResult(true, gl::Error(GL_NO_ERROR)); } @@ -1056,24 +1462,20 @@ GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLo return GL_TRUE; } -void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks, - std::vector<gl::LinkedUniform> *uniforms) +void ProgramD3D::initUniformBlockInfo() { const gl::Shader *vertexShader = mData.getAttachedVertexShader(); - BlockInfoMap blockInfo; - std::map<std::string, size_t> blockDataSizes; - for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks()) { if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED) continue; - if (blockDataSizes.count(vertexBlock.name) > 0) + if (mBlockDataSizes.count(vertexBlock.name) > 0) continue; - size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo); - blockDataSizes[vertexBlock.name] = dataSize; + size_t dataSize = getUniformBlockInfo(vertexBlock); + mBlockDataSizes[vertexBlock.name] = dataSize; } const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); @@ -1083,55 +1485,50 @@ void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBl if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED) continue; - if (blockDataSizes.count(fragmentBlock.name) > 0) + if (mBlockDataSizes.count(fragmentBlock.name) > 0) continue; - size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo); - blockDataSizes[fragmentBlock.name] = dataSize; + size_t dataSize = getUniformBlockInfo(fragmentBlock); + mBlockDataSizes[fragmentBlock.name] = dataSize; } +} - // Copy block info out to uniforms. - for (gl::LinkedUniform &linkedUniform : *uniforms) - { - const auto &infoEntry = blockInfo.find(linkedUniform.name); - - if (infoEntry != blockInfo.end()) - { - linkedUniform.blockInfo = infoEntry->second; - } - } +void ProgramD3D::assignUniformBlockRegisters() +{ + mD3DUniformBlocks.clear(); // Assign registers and update sizes. - const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader); - const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader); + const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader()); - for (gl::UniformBlock &uniformBlock : *uniformBlocks) + for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks()) { unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0; + D3DUniformBlock d3dUniformBlock; + if (uniformBlock.vertexStaticUse) { unsigned int baseRegister = vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name); - uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement; + d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement; } if (uniformBlock.fragmentStaticUse) { unsigned int baseRegister = fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name); - uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement; + d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement; } - ASSERT(blockDataSizes.count(uniformBlock.name) == 1); - uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]); + mD3DUniformBlocks.push_back(d3dUniformBlock); } } void ProgramD3D::initializeUniformStorage() { // Compute total default block size - unsigned int vertexRegisters = 0; + unsigned int vertexRegisters = 0; unsigned int fragmentRegisters = 0; for (const D3DUniform *d3dUniform : mD3DUniforms) { @@ -1150,15 +1547,15 @@ void ProgramD3D::initializeUniformStorage() } } - mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); + mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); } -gl::Error ProgramD3D::applyUniforms() +gl::Error ProgramD3D::applyUniforms(GLenum drawMode) { updateSamplerMapping(); - gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms); + gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms); if (error.isError()) { return error; @@ -1174,26 +1571,36 @@ gl::Error ProgramD3D::applyUniforms() gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) { + if (mData.getUniformBlocks().empty()) + { + return gl::Error(GL_NO_ERROR); + } + + // Lazy init. + if (mD3DUniformBlocks.empty()) + { + assignUniformBlockRegisters(); + } + mVertexUBOCache.clear(); mFragmentUBOCache.clear(); const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); - const auto &uniformBlocks = mData.getUniformBlocks(); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size(); uniformBlockIndex++) { - const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex]; - GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex); + const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex]; + GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex); // Unnecessary to apply an unreferenced standard or shared UBO - if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse) + if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse()) { continue; } - if (uniformBlock.vertexStaticUse) + if (uniformBlock.vertexStaticUse()) { unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS; ASSERT(registerIndex < data.caps->maxVertexUniformBlocks); @@ -1207,7 +1614,7 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) mVertexUBOCache[registerIndex] = blockBinding; } - if (uniformBlock.fragmentStaticUse) + if (uniformBlock.fragmentStaticUse()) { unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS; ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks); @@ -1233,7 +1640,7 @@ void ProgramD3D::dirtyAllUniforms() } } -void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) +void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { setUniform(location, count, v, GL_FLOAT); } @@ -1253,47 +1660,74 @@ void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) setUniform(location, count, v, GL_FLOAT_VEC4); } -void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); } -void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); } -void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); } -void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); } -void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); } -void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); } -void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); } -void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); } -void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); } @@ -1338,14 +1772,15 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); } -void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) +void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, + GLuint /*uniformBlockBinding*/) { } void ProgramD3D::defineUniformsAndAssignRegisters() { D3DUniformMap uniformMap; - const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); for (const sh::Uniform &vertexUniform : vertexShader->getUniforms()) { @@ -1355,7 +1790,7 @@ void ProgramD3D::defineUniformsAndAssignRegisters() } } - const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms()) { if (fragmentUniform.staticUse) @@ -1429,7 +1864,7 @@ void ProgramD3D::defineUniform(GLenum shaderType, for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const std::string &fieldFullName = (fullName + elementString + "." + field.name); defineUniform(shaderType, field, fieldFullName, encoder, uniformMap); @@ -1490,19 +1925,9 @@ void ProgramD3D::defineUniform(GLenum shaderType, } 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> void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType) { - const int components = gl::VariableComponentCount(targetUniformType); + const int components = gl::VariableComponentCount(targetUniformType); const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); D3DUniform *targetUniform = getD3DUniformFromLocation(location); @@ -1517,7 +1942,7 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum for (unsigned int i = 0; i < count; i++) { - T *dest = target + (i * 4); + T *dest = target + (i * 4); const T *source = v + (i * components); for (int c = 0; c < components; c++) @@ -1536,12 +1961,13 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum for (unsigned int i = 0; i < count; i++) { - GLint *dest = boolParams + (i * 4); + 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); + SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, + &targetUniform->dirty); } for (int c = components; c < 4; c++) { @@ -1559,8 +1985,8 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum for (unsigned int i = 0; i < count; i++) { - GLint *dest = target + (i * 4); - const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components); + 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); @@ -1573,75 +1999,8 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum mDirtySamplerMapping = true; } } - else UNREACHABLE(); -} - -template<typename T> -bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) - { - for (int y = 0; y < copyHeight; y++) - { - SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyWidth; y++) - { - for (int x = copyHeight; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - - return dirty; -} - -template<typename T> -bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); - - for (int y = 0; y < copyHeight; y++) - { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) - { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - - return dirty; + else + UNREACHABLE(); } template <int cols, int rows> @@ -1666,19 +2025,20 @@ void ProgramD3D::setUniformMatrixfv(GLint location, // 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; + targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || + targetUniform->dirty; } else { - targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty; + targetUniform->dirty = + ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty; } target += targetMatrixStride; value += cols * rows; } } -size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, - BlockInfoMap *blockInfoOut) +size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock) { ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED); @@ -1697,7 +2057,7 @@ size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, } GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout, - blockInfoOut); + &mBlockInfo); return encoder->getBlockSize(); } @@ -1757,7 +2117,11 @@ void ProgramD3D::reset() { SafeDeleteContainer(mVertexExecutables); SafeDeleteContainer(mPixelExecutables); - SafeDelete(mGeometryExecutable); + + for (auto &element : mGeometryExecutables) + { + SafeDelete(element); + } mVertexHLSL.clear(); mVertexWorkarounds = D3DCompilerWorkarounds(); @@ -1767,8 +2131,10 @@ void ProgramD3D::reset() mUsesFragDepth = false; mPixelShaderKey.clear(); mUsesPointSize = false; + mUsesFlatInterpolation = false; SafeDeleteContainer(mD3DUniforms); + mD3DUniformBlocks.clear(); SafeDelete(mVertexUniformStorage); SafeDelete(mFragmentUniformStorage); @@ -1777,13 +2143,15 @@ void ProgramD3D::reset() mSamplersVS.clear(); mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mDirtySamplerMapping = true; + mUsedPixelSamplerRange = 0; + mDirtySamplerMapping = true; std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1); std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); - mTransformFeedbackLinkedVaryings.clear(); + mStreamOutVaryings.clear(); + + mGeometryShaderPreamble.clear(); } unsigned int ProgramD3D::getSerial() const @@ -1828,15 +2196,16 @@ void ProgramD3D::initAttributesByLayout() AttributeSorter(mSemanticIndexes)); } -void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes, - int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], - const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const +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) { - int oldIndex = mAttributesByLayout[attribIndex]; + int oldIndex = mAttributesByLayout[attribIndex]; sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex]; - sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex]; + sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex]; } } @@ -1862,19 +2231,66 @@ void ProgramD3D::updateCachedInputLayout(const gl::State &state) } } -void ProgramD3D::gatherTransformFeedbackVaryings( - const std::vector<gl::LinkedVarying> &linkedVaryings) +void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking) { + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + + const std::string &varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize()); + // Gather the linked varyings that are used for transform feedback, they should all exist. - mTransformFeedbackLinkedVaryings.clear(); - for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames()) + mStreamOutVaryings.clear(); + + const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames(); + for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size()); + ++outputSlot) { - for (const gl::LinkedVarying &linkedVarying : linkedVaryings) + const auto &tfVaryingName = tfVaryingNames[outputSlot]; + if (tfVaryingName == "gl_Position") { - if (tfVaryingName == linkedVarying.name) + if (builtins.glPosition.enabled) { - mTransformFeedbackLinkedVaryings.push_back(linkedVarying); - break; + mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic, + builtins.glPosition.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_FragCoord") + { + if (builtins.glFragCoord.enabled) + { + mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic, + builtins.glFragCoord.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_PointSize") + { + if (builtins.glPointSize.enabled) + { + mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot)); + } + } + else + { + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &varying = *registerInfo.packedVarying->varying; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + int componentCount = gl::VariableColumnCount(transposedType); + ASSERT(!varying.isBuiltIn()); + + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (registerInfo.packedVarying->isStructField() || varying.isStruct()) + continue; + + // There can be more than one register assigned to a particular varying, and each + // register needs its own stream out entry. + if (tfVaryingName == varying.name) + { + mStreamOutVaryings.push_back(D3DVarying( + varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot)); + } } } } @@ -1884,4 +2300,34 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) { return mD3DUniforms[mData.getUniformLocations()[location].index]; } + +bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const +{ + std::string baseName = blockName; + gl::ParseAndStripArrayIndex(&baseName); + + auto sizeIter = mBlockDataSizes.find(baseName); + if (sizeIter == mBlockDataSizes.end()) + { + *sizeOut = 0; + return false; + } + + *sizeOut = sizeIter->second; + return true; +} + +bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const +{ + auto infoIter = mBlockInfo.find(memberUniformName); + if (infoIter == mBlockInfo.end()) + { + *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; + } + + *memberInfoOut = infoIter->second; + return true; +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h index ba0530f2c06..5ea15aa8b96 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -68,6 +68,66 @@ struct D3DUniform : angle::NonCopyable unsigned int registerElement; }; +struct D3DUniformBlock +{ + D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {} + + bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } + + bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } + + unsigned int vsRegisterIndex; + unsigned int psRegisterIndex; +}; + +struct D3DVarying final +{ + D3DVarying(); + D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn); + + D3DVarying(const D3DVarying &) = default; + D3DVarying &operator=(const D3DVarying &) = default; + + std::string semanticName; + unsigned int semanticIndex; + unsigned int componentCount; + unsigned int outputSlot; +}; + +class ProgramD3DMetadata : angle::NonCopyable +{ + public: + ProgramD3DMetadata(int rendererMajorShaderModel, + const std::string &shaderModelSuffix, + bool usesInstancedPointSpriteEmulation, + 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 usesPointCoord() const; + bool usesFragCoord() const; + bool usesPointSize() const; + bool usesInsertedPointCoordValue() const; + bool addsPointCoordToVertexShader() const; + bool usesTransformFeedbackGLPosition() const; + bool usesSystemValuePointSize() const; + bool usesMultipleFragmentOuts() const; + GLint getMajorShaderVersion() const; + const ShaderD3D *getFragmentShader() const; + + private: + const int mRendererMajorShaderModel; + const std::string mShaderModelSuffix; + const bool mUsesInstancedPointSpriteEmulation; + const ShaderD3D *mVertexShader; + const ShaderD3D *mFragmentShader; +}; + class ProgramD3D : public ProgramImpl { public: @@ -78,32 +138,44 @@ class ProgramD3D : public ProgramImpl const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } - GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; + GLint getSamplerMapping(gl::SamplerType type, + 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(); bool usesPointSize() const { return mUsesPointSize; } bool usesPointSpriteEmulation() const; - bool usesGeometryShader() const; + bool usesGeometryShader(GLenum drawMode) const; bool usesInstancedPointSpriteEmulation() const; - LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); - gl::Error save(gl::BinaryOutputStream *stream); - - 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); - ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; } + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; + gl::Error save(gl::BinaryOutputStream *stream) override; + void setBinaryRetrievableHint(bool retrievable) override; + + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog); LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; - void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks, - std::vector<gl::LinkedUniform> *uniforms) override; + bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; + bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const override; void initializeUniformStorage(); - gl::Error applyUniforms(); + gl::Error applyUniforms(GLenum drawMode); gl::Error applyUniformBuffers(const gl::Data &data); void dirtyAllUniforms(); @@ -119,15 +191,42 @@ class ProgramD3D : public ProgramImpl void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); - void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; @@ -136,9 +235,10 @@ class ProgramD3D : public ProgramImpl 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; + 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; } @@ -174,10 +274,14 @@ class ProgramD3D : public ProgramImpl class PixelExecutable { public: - PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable); + PixelExecutable(const std::vector<GLenum> &outputSignature, + ShaderExecutableD3D *shaderExecutable); ~PixelExecutable(); - bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; } + bool matchesSignature(const std::vector<GLenum> &signature) const + { + return mOutputSignature == signature; + } const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } @@ -197,7 +301,6 @@ class ProgramD3D : public ProgramImpl }; typedef std::map<std::string, D3DUniform *> D3DUniformMap; - typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap; void defineUniformsAndAssignRegisters(); void defineUniformBase(const gl::Shader *shader, @@ -217,19 +320,19 @@ class ProgramD3D : public ProgramImpl std::vector<Sampler> &outSamplers, GLuint *outUsedRange); - size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut); - template <typename T> - void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); + void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType); template <int cols, int rows> - void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); + void setUniformMatrixfv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType); - LinkResult compileProgramExecutables(gl::InfoLog &infoLog, - int registers, - const std::vector<PackedVarying> &packedVaryings); + LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog); - void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings); + void gatherTransformFeedbackVaryings(const VaryingPacking &varyings); D3DUniform *getD3DUniformByName(const std::string &name); D3DUniform *getD3DUniformFromLocation(GLint location); @@ -237,13 +340,17 @@ class ProgramD3D : public ProgramImpl void initAttributesByLayout(); void reset(); + void assignUniformBlockRegisters(); + + void initUniformBlockInfo(); + size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock); RendererD3D *mRenderer; DynamicHLSL *mDynamicHLSL; std::vector<VertexExecutable *> mVertexExecutables; std::vector<PixelExecutable *> mPixelExecutables; - ShaderExecutableD3D *mGeometryExecutable; + std::vector<ShaderExecutableD3D *> mGeometryExecutables; std::string mVertexHLSL; D3DCompilerWorkarounds mVertexWorkarounds; @@ -253,7 +360,13 @@ class ProgramD3D : public ProgramImpl bool mUsesFragDepth; std::vector<PixelShaderOutputVariable> mPixelShaderKey; + // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output + // structures, built from the linked varying info. We store the string itself instead of the + // packed varyings for simplicity. + std::string mGeometryShaderPreamble; + bool mUsesPointSize; + bool mUsesFlatInterpolation; UniformStorageD3D *mVertexUniformStorage; UniformStorageD3D *mFragmentUniformStorage; @@ -277,13 +390,16 @@ class ProgramD3D : public ProgramImpl VertexExecutable::Signature mCachedVertexSignature; gl::InputLayout mCachedInputLayout; - std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings; + std::vector<D3DVarying> mStreamOutVaryings; std::vector<D3DUniform *> mD3DUniforms; + std::vector<D3DUniformBlock> mD3DUniformBlocks; + + std::map<std::string, sh::BlockMemberInfo> mBlockInfo; + std::map<std::string, size_t> mBlockDataSizes; static unsigned int issueSerial(); static unsigned int mCurrentSerial; }; - } -#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp index 26740aadc99..575ecd636e9 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -8,22 +8,23 @@ #include "libANGLE/renderer/d3d/RendererD3D.h" -#include "common/MemoryBuffer.h" #include "common/debug.h" +#include "common/MemoryBuffer.h" #include "common/utilities.h" #include "libANGLE/Display.h" +#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" -#include "libANGLE/ResourceManager.h" -#include "libANGLE/State.h" -#include "libANGLE/VertexArray.h" -#include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" #include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" namespace rx { @@ -134,12 +135,6 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, GLsizei instances, const gl::IndexRange &indexRange) { - if (data.state->isPrimitiveRestartEnabled()) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented"); - } - gl::Program *program = data.state->getProgram(); ASSERT(program != nullptr); ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); @@ -158,25 +153,18 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, return gl::Error(GL_NO_ERROR); } - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); + error = updateState(data, mode); if (error.isError()) { return error; } - gl::VertexArray *vao = data.state->getVertexArray(); TranslatedIndexData indexInfo; indexInfo.indexRange = indexRange; SourceIndexData sourceIndexInfo; - error = applyIndexBuffer(indices, vao->getElementArrayBuffer().get(), count, mode, type, &indexInfo, &sourceIndexInfo); + error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo, &sourceIndexInfo); if (error.isError()) { return error; @@ -195,7 +183,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, return error; } - error = applyShaders(data); + error = applyShaders(data, mode); if (error.isError()) { return error; @@ -215,8 +203,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, if (!skipDraw(data, mode)) { - error = drawElementsImpl(mode, count, type, indices, vao->getElementArrayBuffer().get(), - indexInfo, instances, usesPointSize); + error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances); if (error.isError()) { return error; @@ -250,13 +237,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data, return gl::Error(GL_NO_ERROR); } - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); + error = updateState(data, mode); if (error.isError()) { return error; @@ -270,7 +251,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data, return error; } - error = applyShaders(data); + error = applyShaders(data, mode); if (error.isError()) { return error; @@ -290,7 +271,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data, if (!skipDraw(data, mode)) { - error = drawArraysImpl(data, mode, count, instances, usesPointSize); + error = drawArraysImpl(data, mode, count, instances); if (error.isError()) { return error; @@ -350,45 +331,8 @@ gl::Error RendererD3D::generateSwizzles(const gl::Data &data) return gl::Error(GL_NO_ERROR); } -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ = data.state->getNearPlane(); - float farZ = data.state->getFarPlane(); - setViewport(data.state->getViewport(), nearZ, farZ, drawMode, - data.state->getRasterizerState().frontFace, ignoreViewport); - - setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device -gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) +unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples) { - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - int samples = framebufferObject->getSamples(data); - - gl::RasterizerState rasterizer = data.state->getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - gl::Error error = setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - unsigned int mask = 0; if (data.state->isSampleCoverageEnabled()) { @@ -419,38 +363,24 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) { mask = 0xFFFFFFFF; } - error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), - data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - return gl::Error(GL_NO_ERROR); + return mask; } // Applies the shaders and shader constants to the Direct3D device -gl::Error RendererD3D::applyShaders(const gl::Data &data) +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); - const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); - - gl::Error error = applyShaders(program, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused()); + gl::Error error = applyShadersImpl(data, drawMode); if (error.isError()) { return error; } - return programD3D->applyUniforms(); + return programD3D->applyUniforms(drawMode); } // For each Direct3D sampler of either the pixel or vertex stage, @@ -497,7 +427,15 @@ gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shade { // 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 = setTexture(shaderType, samplerIndex, incompleteTexture); + + gl::Error error = setSamplerState(shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState()); + if (error.isError()) + { + return error; + } + + error = setTexture(shaderType, samplerIndex, incompleteTexture); if (error.isError()) { return error; @@ -742,5 +680,4 @@ gl::DebugAnnotator *RendererD3D::getAnnotator() ASSERT(mAnnotator); return mAnnotator; } - } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h index b6c29b934b9..4a90fd12d94 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -12,7 +12,8 @@ #include "common/debug.h" #include "common/MemoryBuffer.h" #include "libANGLE/Data.h" -#include "libANGLe/formatutils.h" +#include "libANGLE/Device.h" +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/Renderer.h" #include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/formatutilsD3D.h" @@ -29,15 +30,17 @@ class ConfigSet; namespace gl { +class DebugAnnotator; class InfoLog; -struct LinkedVarying; class Texture; -class DebugAnnotator; +struct LinkedVarying; } namespace rx { struct D3DUniform; +struct D3DVarying; +class DeviceD3D; class EGLImageD3D; class ImageD3D; class IndexBuffer; @@ -53,7 +56,8 @@ enum ShaderType { SHADER_VERTEX, SHADER_PIXEL, - SHADER_GEOMETRY + SHADER_GEOMETRY, + SHADER_TYPE_MAX }; struct DeviceIdentifier @@ -139,7 +143,11 @@ class RendererD3D : public Renderer, public BufferFactoryD3D // Direct3D Specific methods virtual DeviceIdentifier getAdapterIdentifier() const = 0; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + 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; @@ -149,26 +157,21 @@ class RendererD3D : public Renderer, public BufferFactoryD3D const std::vector<GLint> &vertexUniformBuffers, const std::vector<GLint> &fragmentUniformBuffers) = 0; - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) = 0; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) = 0; - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) = 0; + virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0; virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyShaders(gl::Program *program, - const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, - bool transformFeedbackActive) = 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, SourceIndexData *sourceIndexInfo) = 0; - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) = 0; + virtual gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo, + SourceIndexData *sourceIndexInfo) = 0; virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; virtual void markAllStateDirty() = 0; @@ -197,12 +200,18 @@ class RendererD3D : public Renderer, public BufferFactoryD3D virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0; - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + virtual gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) = 0; + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) = 0; virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; @@ -223,11 +232,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; - void syncState(const gl::State & /*state*/, const gl::State::DirtyBits &bitmask) override - { - // TODO(jmadill): implement state sync for D3D renderers; - } - // Device lost void notifyDeviceLost() override; virtual bool resetDevice() = 0; @@ -244,13 +248,17 @@ class RendererD3D : public Renderer, public BufferFactoryD3D // In D3D11, faster than calling setTexture a jillion times virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0; + virtual egl::Error getEGLDevice(DeviceImpl **device) = 0; + protected: virtual bool getLUID(LUID *adapterLuid) const = 0; + virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 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. static const uintptr_t DirtyPointer; @@ -280,16 +288,14 @@ class RendererD3D : public Renderer, public BufferFactoryD3D virtual gl::Error drawArraysImpl(const gl::Data &data, GLenum mode, GLsizei count, - GLsizei instances, - bool usesPointSize) = 0; - virtual gl::Error drawElementsImpl(GLenum mode, + GLsizei instances) = 0; + virtual gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, - const TranslatedIndexData &indexInfo, - GLsizei instances, - bool usesPointSize) = 0; + 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; @@ -297,9 +303,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); gl::Error generateSwizzles(const gl::Data &data); - gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); gl::Error applyState(const gl::Data &data, GLenum drawMode); - gl::Error applyShaders(const gl::Data &data); + 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); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp index 07bd10d134e..1ecbfb74104 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -117,23 +117,24 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const return mCompilerOutputType; } -int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream) +int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream, + std::string *sourcePath) { uncompile(); int additionalOptions = 0; -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) const std::string &source = mData.getSource(); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) if (gl::DebugAnnotationsActive()) { - std::string sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), source.c_str(), source.length()); + *sourcePath = getTempPath(); + writeFile(sourcePath->c_str(), source.c_str(), source.length()); additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH; - *shaderSourceStream << sourcePath; } #endif + *shaderSourceStream << source; return additionalOptions; } @@ -191,15 +192,11 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo } } -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED mDebugInfo += - std::string("// ") + GetShaderTypeString(mData->getShaderType()) + " SHADER BEGIN\n"; - mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; + std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n"; + mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n"; mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n"; // Successive steps will append more info -#else - mDebugInfo += translatedSource; -#endif return true; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h index f61917a7efc..47a73dc27b4 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -21,14 +21,13 @@ struct D3DCompilerWorkarounds; class ShaderD3D : public ShaderImpl { - friend class DynamicHLSL; - public: ShaderD3D(const gl::Shader::Data &data); virtual ~ShaderD3D(); // ShaderImpl implementation - int prepareSourceAndReturnOptions(std::stringstream *sourceStream) override; + int prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) override; bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; std::string getDebugInfo() const override; @@ -36,13 +35,20 @@ class ShaderD3D : public ShaderImpl void uncompile(); unsigned int getUniformRegister(const std::string &uniformName) const; unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - void appendDebugInfo(const std::string &info) { mDebugInfo += info; } + void appendDebugInfo(const std::string &info) const { mDebugInfo += info; } void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; - bool usesDepthRange() const { return mUsesDepthRange; } + + bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; } + bool usesFragColor() const { return mUsesFragColor; } + bool usesFragData() const { return mUsesFragData; } + bool usesFragCoord() const { return mUsesFragCoord; } + bool usesFrontFacing() const { return mUsesFrontFacing; } bool usesPointSize() const { return mUsesPointSize; } + bool usesPointCoord() const { return mUsesPointCoord; } + bool usesDepthRange() const { return mUsesDepthRange; } + bool usesFragDepth() const { return mUsesFragDepth; } bool usesDeferredInit() const { return mUsesDeferredInit; } - bool usesFrontFacing() const { return mUsesFrontFacing; } ShShaderOutput getCompilerOutputType() const; @@ -62,11 +68,10 @@ class ShaderD3D : public ShaderImpl bool mRequiresIEEEStrictCompiling; ShShaderOutput mCompilerOutputType; - std::string mDebugInfo; + mutable std::string mDebugInfo; std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; }; - } -#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index 77685f06d70..93f69904a3d 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -24,13 +24,22 @@ 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, shareHandle, NULL); + 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 width, EGLint height) +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, static_cast<EGLClientBuffer>(0), window); + return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation, + directComposition, static_cast<EGLClientBuffer>(0), window); } SurfaceD3D::SurfaceD3D(RendererD3D *renderer, @@ -39,17 +48,20 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer, EGLint width, EGLint height, EGLint fixedSize, + EGLint orientation, + EGLint directComposition, EGLClientBuffer shareHandle, EGLNativeWindowType window) : SurfaceImpl(), mRenderer(renderer), mDisplay(display), mFixedSize(fixedSize == EGL_TRUE), + mOrientation(orientation), mRenderTargetFormat(config->renderTargetFormat), mDepthStencilFormat(config->depthStencilFormat), mSwapChain(nullptr), mSwapIntervalDirty(true), - mNativeWindow(window, config), + mNativeWindow(window, config, directComposition == EGL_TRUE), mWidth(width), mHeight(height), mSwapInterval(1), @@ -91,7 +103,7 @@ FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Dat return mRenderer->createFramebuffer(data); } -egl::Error SurfaceD3D::bindTexImage(EGLint) +egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint) { return egl::Error(EGL_SUCCESS); } @@ -128,7 +140,8 @@ egl::Error SurfaceD3D::resetSwapChain() height = mHeight; } - mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, + mDepthStencilFormat, mOrientation); if (!mSwapChain) { return egl::Error(EGL_BAD_ALLOC); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h index e6f727aeacf..b925bfc8cc7 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -25,8 +25,15 @@ class RendererD3D; class SurfaceD3D : public SurfaceImpl { public: - static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, - EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height); + 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; @@ -38,7 +45,7 @@ class SurfaceD3D : public SurfaceImpl egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; @@ -60,8 +67,16 @@ class SurfaceD3D : public SurfaceImpl FramebufferAttachmentRenderTarget **rtOut) override; private: - SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, - EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window); + SurfaceD3D(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); @@ -71,6 +86,7 @@ class SurfaceD3D : public SurfaceImpl egl::Display *mDisplay; bool mFixedSize; + GLint mOrientation; GLenum mRenderTargetFormat; GLenum mDepthStencilFormat; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp index 0687ac89c81..cdb2c474715 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -165,14 +165,6 @@ gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index, const uint8_t *pixels, ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - // TODO(jmadill): additional unpack parameters - // return no error here to work around dEQP-GLES3 failing to state reset. - UNIMPLEMENTED(); - return gl::Error(GL_NO_ERROR); - } - ImageD3D *image = getImage(index); ASSERT(image); @@ -258,12 +250,6 @@ gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index, const uint8_t *pixels, ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - // 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; @@ -295,12 +281,6 @@ gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl:: const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - const uint8_t *pixelData = NULL; gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) @@ -333,6 +313,15 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget) { + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || + unpack.skipImages != 0) + { + // TODO(jmadill): additional unpack parameters + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, + "Unimplemented pixel store parameters in fastUnpackPixels"); + } + // No-op if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) { @@ -765,12 +754,6 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target, { ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - GLint level = static_cast<GLint>(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2D(level); if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) @@ -2563,7 +2546,8 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, redefineImage(level, sizedInternalFormat, size); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch( + type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); for (int i = 0; i < size.depth; i++) { @@ -2590,7 +2574,8 @@ 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); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch( + type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); for (int i = 0; i < area.depth; i++) { @@ -2625,7 +2610,8 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, redefineImage(level, internalFormat, size); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0); for (int i = 0; i < size.depth; i++) { @@ -2648,7 +2634,8 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, 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); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); for (int i = 0; i < area.depth; i++) { diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp new file mode 100644 index 00000000000..f2654d34e33 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp @@ -0,0 +1,397 @@ +// +// 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/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h new file mode 100644 index 00000000000..ca4640b0002 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h @@ -0,0 +1,175 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers in D3D +// for linking between shader stages. +// + +#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ +#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ +class ProgramD3DMetadata; + +struct PackedVarying +{ + PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn) + : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn) + { + } + PackedVarying(const sh::ShaderVariable &varyingIn, + sh::InterpolationType interpolationIn, + const std::string &parentStructNameIn) + : varying(&varyingIn), + vertexOnly(false), + interpolation(interpolationIn), + parentStructName(parentStructNameIn) + { + } + + bool isStructField() const { return !parentStructName.empty(); } + + const sh::ShaderVariable *varying; + + // Transform feedback varyings can be only referenced in the VS. + bool vertexOnly; + + // Cached so we can store sh::ShaderVariable to point to varying fields. + sh::InterpolationType interpolation; + + // Struct name + std::string parentStructName; +}; + +struct PackedVaryingRegister final +{ + PackedVaryingRegister() + : packedVarying(nullptr), + varyingArrayIndex(0), + varyingRowIndex(0), + registerRow(0), + registerColumn(0) + { + } + + PackedVaryingRegister(const PackedVaryingRegister &) = default; + PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; + + bool operator<(const PackedVaryingRegister &other) const + { + return sortOrder() < other.sortOrder(); + } + + unsigned int sortOrder() const + { + // TODO(jmadill): Handle interpolation types + return registerRow * 4 + registerColumn; + } + + bool isStructField() const { return !structFieldName.empty(); } + + // Index to the array of varyings. + const PackedVarying *packedVarying; + + // The array element of the packed varying. + unsigned int varyingArrayIndex; + + // The row of the array element of the packed varying. + unsigned int varyingRowIndex; + + // The register row to which we've assigned this packed varying. + unsigned int registerRow; + + // The column of the register row into which we've packed this varying. + unsigned int registerColumn; + + // Assigned after packing + unsigned int semanticIndex; + + // Struct member this varying corresponds to. + std::string structFieldName; +}; + +class VaryingPacking final : angle::NonCopyable +{ + public: + VaryingPacking(GLuint maxVaryingVectors); + + bool packVaryings(gl::InfoLog &infoLog, + const std::vector<PackedVarying> &packedVaryings, + const std::vector<std::string> &transformFeedbackVaryings); + + struct Register + { + Register() { data[0] = data[1] = data[2] = data[3] = false; } + + bool &operator[](unsigned int index) { return data[index]; } + bool operator[](unsigned int index) const { return data[index]; } + + bool data[4]; + }; + + Register &operator[](unsigned int index) { return mRegisterMap[index]; } + const Register &operator[](unsigned int index) const { return mRegisterMap[index]; } + + const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; } + unsigned int getMaxSemanticIndex() const + { + return static_cast<unsigned int>(mRegisterList.size()); + } + unsigned int getRegisterCount() const; + + void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata); + + struct BuiltinVarying final : angle::NonCopyable + { + BuiltinVarying(); + + std::string str() const; + void enableSystem(const std::string &systemValueSemantic); + void enable(const std::string &semanticVal, unsigned int indexVal); + + bool enabled; + std::string semantic; + unsigned int index; + bool systemValue; + }; + + struct BuiltinInfo + { + BuiltinVarying dxPosition; + BuiltinVarying glPosition; + BuiltinVarying glFragCoord; + BuiltinVarying glPointCoord; + BuiltinVarying glPointSize; + }; + + const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; } + + bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; } + + private: + bool packVarying(const PackedVarying &packedVarying); + bool isFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const; + void insert(unsigned int registerRow, + unsigned int registerColumn, + const PackedVarying &packedVarying); + + std::vector<Register> mRegisterMap; + std::vector<PackedVaryingRegister> mRegisterList; + + std::vector<BuiltinInfo> mBuiltinInfo; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp index 51ea6ef475b..9efee9db7ca 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -243,7 +243,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) } StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) - : VertexBufferInterface(factory, false) + : VertexBufferInterface(factory, false), mIsCommitted(false) { } @@ -255,13 +255,14 @@ bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &att { for (unsigned int element = 0; element < mCache.size(); element++) { - if (mCache[element].type == attrib.type && - mCache[element].size == attrib.size && - mCache[element].stride == ComputeVertexAttributeStride(attrib) && + 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) % ComputeVertexAttributeStride(attrib)); + size_t offset = (static_cast<size_t>(attrib.offset) % attribStride); if (mCache[element].attributeOffset == offset) { if (outStreamOffset) @@ -321,4 +322,11 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt return gl::Error(GL_NO_ERROR); } +void StaticVertexBufferInterface::commit() +{ + if (getBufferSize() > 0) + { + mIsCommitted = true; + } +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h index 81a90f68245..692b6ac5062 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -135,6 +135,11 @@ class StaticVertexBufferInterface : public VertexBufferInterface bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); + // 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; } + protected: gl::Error reserveSpace(unsigned int size); @@ -151,6 +156,7 @@ class StaticVertexBufferInterface : public VertexBufferInterface unsigned int streamOffset; }; + bool mIsCommitted; std::vector<VertexElement> mCache; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index 559e633eaa8..b392d0f4da2 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -88,10 +88,17 @@ void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttrib { gl::Buffer *buffer = translated->attribute->buffer.get(); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : 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(); } } @@ -146,10 +153,14 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, { mActiveEnabledAttributes.push_back(translated); - // Also invalidate static buffers that don't contain matching attributes - invalidateMatchingStaticData( - vertexAttributes[attribIndex], - state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex))); + 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(); + } } else { @@ -215,26 +226,6 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, return gl::Error(GL_NO_ERROR); } -void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const -{ - gl::Buffer *buffer = attrib.buffer.get(); - - if (buffer) - { - BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); - StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); - - if (staticBuffer && - staticBuffer->getBufferSize() > 0 && - !staticBuffer->lookupAttribute(attrib, NULL) && - !staticBuffer->directStoragePossible(attrib, currentValue.Type)) - { - bufferImpl->invalidateStaticData(); - } - } -} - gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, GLsizei count, GLsizei instances) const @@ -242,7 +233,9 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &tr const gl::VertexAttribute &attrib = *translatedAttrib.attribute; gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : 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)) @@ -291,12 +284,13 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, ASSERT(attrib.enabled); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : 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); // Instanced vertices do not apply the 'start' offset - GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); + GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start); translated->vertexBuffer = vertexBuffer->getVertexBuffer(); @@ -363,7 +357,8 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, (static_cast<unsigned int>(attrib.offset) / static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) * outputElementSize; - unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; + ASSERT(attrib.divisor == 0 || firstVertexIndex == 0); + unsigned int startOffset = firstVertexIndex * outputElementSize; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return gl::Error(GL_OUT_OF_MEMORY); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h index f03c777bee3..fb349c4cc2e 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -82,9 +82,6 @@ class VertexDataManager : angle::NonCopyable GLsizei count, GLsizei instances) const; - void invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const; - gl::Error storeAttribute(TranslatedAttribute *translated, GLint start, GLsizei count, diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp index 3b42c981777..68776774a28 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -196,6 +196,23 @@ inline unsigned int GetSwizzleIndex(GLenum swizzle) return colorIndex; } +D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc() +{ + D3D11_BLEND_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | + D3D11_COLOR_WRITE_ENABLE_GREEN | + D3D11_COLOR_WRITE_ENABLE_BLUE; + return desc; +} + D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, @@ -213,21 +230,57 @@ D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = Blit11::Blit11(Renderer11 *renderer) : mRenderer(renderer), + mResourcesInitialized(false), mVertexBuffer(nullptr), mPointSampler(nullptr), mLinearSampler(nullptr), mScissorEnabledRasterizerState(nullptr), mScissorDisabledRasterizerState(nullptr), mDepthStencilState(nullptr), - mQuad2DIL(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D input layout"), + mQuad2DIL(quad2DLayout, + ArraySize(quad2DLayout), + g_VS_Passthrough2D, + ArraySize(g_VS_Passthrough2D), + "Blit11 2D input layout"), mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"), - mDepthPS(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), "Blit11 2D depth pixel shader"), - mQuad3DIL(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D input layout"), + mDepthPS(g_PS_PassthroughDepth2D, + ArraySize(g_PS_PassthroughDepth2D), + "Blit11 2D depth pixel shader"), + mQuad3DIL(quad3DLayout, + ArraySize(quad3DLayout), + g_VS_Passthrough3D, + ArraySize(g_VS_Passthrough3D), + "Blit11 3D input layout"), mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"), mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"), + mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"), mSwizzleCB(nullptr) { - TRACE_EVENT0("gpu.angle", "Blit11::Blit11"); +} + +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); + } + + TRACE_EVENT0("gpu.angle", "Blit11::initResources"); HRESULT result; ID3D11Device *device = mRenderer->getDevice(); @@ -236,7 +289,7 @@ Blit11::Blit11(Renderer11 *renderer) vbDesc.ByteWidth = static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * - 6 * renderer->getRendererCaps().max3DTextureSize); + 6 * mRenderer->getRendererCaps().max3DTextureSize); vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -245,6 +298,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); D3D11_SAMPLER_DESC pointSamplerDesc; @@ -264,6 +323,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit point sampler state, HRESULT: 0x%X", result); + } d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); D3D11_SAMPLER_DESC linearSamplerDesc; @@ -283,6 +348,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit linear sampler state, HRESULT: 0x%X", result); + } d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); // Use a rasterizer state that will not cull so that inverted quads will not be culled @@ -300,11 +371,25 @@ Blit11::Blit11(Renderer11 *renderer) rasterDesc.ScissorEnable = TRUE; result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); rasterDesc.ScissorEnable = FALSE; result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); D3D11_DEPTH_STENCIL_DESC depthStencilDesc; @@ -325,6 +410,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit depth stencil state, HRESULT: 0x%X", result); + } d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); D3D11_BUFFER_DESC swizzleBufferDesc; @@ -337,10 +428,20 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); + + mResourcesInitialized = true; + + return gl::Error(GL_NO_ERROR); } -Blit11::~Blit11() +void Blit11::freeResources() { SafeRelease(mVertexBuffer); SafeRelease(mPointSampler); @@ -348,18 +449,9 @@ Blit11::~Blit11() SafeRelease(mScissorEnabledRasterizerState); SafeRelease(mScissorDisabledRasterizerState); SafeRelease(mDepthStencilState); - - mQuad2DIL.release(); - mQuad2DVS.release(); - mDepthPS.release(); - - mQuad3DIL.release(); - mQuad3DVS.release(); - mQuad3DGS.release(); - SafeRelease(mSwizzleCB); - clearShaderMap(); + mResourcesInitialized = false; } // static @@ -521,6 +613,12 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, GLenum swizzleBlue, GLenum swizzleAlpha) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -550,7 +648,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, } const Shader *shader = nullptr; - gl::Error error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader); + error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader); if (error.isError()) { return error; @@ -649,10 +747,23 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, return gl::Error(GL_NO_ERROR); } -gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -668,7 +779,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; const Shader *shader = nullptr; - gl::Error error = getBlitShader(destFormat, isSigned, dimension, &shader); + error = getBlitShader(destFormat, isSigned, dimension, &shader); if (error.isError()) { return error; @@ -698,7 +809,16 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); // Apply state - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + if (maskOffAlpha) + { + ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice()); + ASSERT(blendState); + deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF); + } + else + { + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + } deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); if (scissor) @@ -787,6 +907,12 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -898,6 +1024,12 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu ID3D11Resource *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; + } + ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h index d3be7917c69..906616131ec 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -29,9 +29,16 @@ class Blit11 : angle::NonCopyable gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + gl::Error copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha); 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, @@ -125,6 +132,9 @@ class Blit11 : angle::NonCopyable WriteVertexFunction vertexWriteFunction; }; + gl::Error initResources(); + void freeResources(); + ShaderSupport getShaderSupport(const Shader &shader); static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension); @@ -148,6 +158,7 @@ class Blit11 : angle::NonCopyable std::map<BlitShaderType, Shader> mBlitShaderMap; std::map<SwizzleShaderType, Shader> mSwizzleShaderMap; + bool mResourcesInitialized; ID3D11Buffer *mVertexBuffer; ID3D11SamplerState *mPointSampler; ID3D11SamplerState *mLinearSampler; @@ -163,6 +174,8 @@ class Blit11 : angle::NonCopyable d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS; d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS; + d3d11::LazyBlendState mAlphaMaskBlendState; + ID3D11Buffer *mSwizzleCB; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index 670561afb1d..7ce85f2a0a5 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -361,7 +361,7 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) } mSize = std::max(mSize, requiredSize); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } @@ -417,7 +417,7 @@ gl::Error Buffer11::copySubData(BufferImpl *source, copyDest->setDataRevision(copyDest->getDataRevision() + 1); mSize = std::max<size_t>(mSize, destOffset + size); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } @@ -457,7 +457,7 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL { // Update the data revision immediately, since the data might be changed at any time mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); @@ -492,7 +492,7 @@ void Buffer11::markTransformFeedbackUsage() transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } void Buffer11::markBufferUsage() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp index 9adef8a59ea..03b28c2a56e 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -229,21 +229,15 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); if (colorAttachment != nullptr) { - framebufferSize.width = colorAttachment->getWidth(); - framebufferSize.height = colorAttachment->getHeight(); - framebufferSize.depth = 1; + framebufferSize = colorAttachment->getSize(); } else if (depthAttachment != nullptr) { - framebufferSize.width = depthAttachment->getWidth(); - framebufferSize.height = depthAttachment->getHeight(); - framebufferSize.depth = 1; + framebufferSize = depthAttachment->getSize(); } else if (stencilAttachment != nullptr) { - framebufferSize.width = stencilAttachment->getWidth(); - framebufferSize.height = stencilAttachment->getHeight(); - framebufferSize.depth = 1; + framebufferSize = stencilAttachment->getSize(); } else { diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp index da4cf3947dd..f9d28e84082 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -39,32 +39,53 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName) { initializeDevice(); - mUserDefinedAnnotation->BeginEvent(eventName); + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->BeginEvent(eventName); + } } void DebugAnnotator11::endEvent() { initializeDevice(); - mUserDefinedAnnotation->EndEvent(); + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->EndEvent(); + } } void DebugAnnotator11::setMarker(const wchar_t *markerName) { initializeDevice(); - mUserDefinedAnnotation->SetMarker(markerName); + if (mUserDefinedAnnotation != nullptr) + { + mUserDefinedAnnotation->SetMarker(markerName); + } } bool DebugAnnotator11::getStatus() { - // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +#if (NTDDI_VERSION == NTDDI_WIN10) + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + return !!(mUserDefinedAnnotation->GetStatus()); + } + + return true; // Default if initializeDevice() failed +#elif defined(_DEBUG) static bool underCapture = true; -#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) - // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // 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. + // 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; @@ -82,9 +103,16 @@ bool DebugAnnotator11::getStatus() SafeRelease(graphicsAnalysis); triedIDXGraphicsAnalysis = true; } -#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE 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; +#endif // ANGLE_ENABLE_WINDOWS_STORE } void DebugAnnotator11::initializeDevice() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp index 76bb15c193b..4a8d39a500f 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -91,7 +91,7 @@ gl::Error Framebuffer11::invalidateSwizzles() const return gl::Error(GL_NO_ERROR); } -gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams) +gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams) { Clear11 *clearer = mRenderer->getClearer(); gl::Error error = clearer->clearFramebuffer(clearParams, mData); @@ -289,7 +289,12 @@ gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectang return gl::Error(GL_NO_ERROR); } -gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const { ID3D11Texture2D *colorBufferTexture = nullptr; unsigned int subresourceIndex = 0; @@ -306,6 +311,13 @@ gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GL gl::Buffer *packBuffer = pack.pixelBuffer.get(); 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)); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h index dfadd58603d..c8a33ec7e59 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -29,10 +29,14 @@ class Framebuffer11 : public FramebufferD3D gl::Error invalidateSwizzles() const; private: - gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; - - gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const override; + gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp index 0d7ae743a91..8d5efed2fa6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -247,7 +247,10 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp { 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); + 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; @@ -264,8 +267,8 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp 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), inputRowPitch, inputDepthPitch, - offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch, + inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); @@ -276,7 +279,8 @@ gl::Error Image11::loadCompressedData(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); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp index 5868612717b..2c86b4842b6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -317,58 +317,11 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri } ID3D11InputLayout *inputLayout = nullptr; - - auto layoutMapIt = mLayoutMap.find(layout); - if (layoutMapIt != mLayoutMap.end()) + gl::Error error = findInputLayout(layout, inputElementCount, inputElements, programD3D, + sortedAttributes, unsortedAttributes.size(), &inputLayout); + if (error.isError()) { - inputLayout = layoutMapIt->second; - } - else - { - const gl::InputLayout &shaderInputLayout = - GetInputLayout(sortedAttributes, unsortedAttributes.size()); - - ShaderExecutableD3D *shader = nullptr; - gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); - if (error.isError()) - { - return error; - } - - ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader); - - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < inputElementCount; ++j) - { - descs[j] = inputElements[j]; - } - - HRESULT result = mDevice->CreateInputLayout(descs, inputElementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); - } - - if (mLayoutMap.size() >= mCacheSize) - { - TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize); - - // Randomly release every second element - auto it = mLayoutMap.begin(); - while (it != mLayoutMap.end()) - { - it++; - if (it != mLayoutMap.end()) - { - // Calling std::map::erase invalidates the current iterator, so make a copy. - auto eraseIt = it++; - SafeRelease(eraseIt->second); - mLayoutMap.erase(eraseIt); - } - } - } - - mLayoutMap[layout] = inputLayout; + return error; } if (inputLayout != mCurrentIL) @@ -406,7 +359,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri if (sourceInfo->srcBuffer != nullptr) { const uint8_t *bufferData = nullptr; - gl::Error error = sourceInfo->srcBuffer->getData(&bufferData); + error = sourceInfo->srcBuffer->getData(&bufferData); if (error.isError()) { return error; @@ -500,6 +453,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri instancedPointSpritesActive ? pointSpriteVertexStride : 0; mCurrentVertexOffsets[nextAvailableIndex] = 0; + // Update maxDiff to include the additional point sprite vertex buffer + // to ensure that IASetVertexBuffers uses the correct buffer count. + maxDiff = std::max(maxDiff, nextAvailableIndex); + if (!mPointSpriteIndexBuffer) { // Create an index buffer and set it for pointsprite rendering @@ -557,4 +514,70 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri return gl::Error(GL_NO_ERROR); } +gl::Error InputLayoutCache::findInputLayout( + const PackedAttributeLayout &layout, + unsigned int inputElementCount, + const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS], + ProgramD3D *programD3D, + const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS], + size_t attributeCount, + ID3D11InputLayout **inputLayout) +{ + if (inputElementCount == 0) + { + *inputLayout = nullptr; + return gl::Error(GL_NO_ERROR); + } + + auto layoutMapIt = mLayoutMap.find(layout); + if (layoutMapIt != mLayoutMap.end()) + { + *inputLayout = layoutMapIt->second; + return gl::Error(GL_NO_ERROR); + } + + const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attributeCount); + + ShaderExecutableD3D *shader = nullptr; + gl::Error error = + programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader); + + HRESULT result = + mDevice->CreateInputLayout(inputElements, inputElementCount, shader11->getFunction(), + shader11->getLength(), inputLayout); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal input layout, HRESULT: 0x%08x", result); + } + + if (mLayoutMap.size() >= mCacheSize) + { + TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize); + + // Randomly release every second element + auto it = mLayoutMap.begin(); + while (it != mLayoutMap.end()) + { + it++; + if (it != mLayoutMap.end()) + { + // Calling std::map::erase invalidates the current iterator, so make a copy. + auto eraseIt = it++; + SafeRelease(eraseIt->second); + mLayoutMap.erase(eraseIt); + } + } + } + + mLayoutMap[layout] = *inputLayout; + return gl::Error(GL_NO_ERROR); } + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h index 4cc0ec9b68a..58edb9c1136 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -31,6 +31,7 @@ namespace rx struct TranslatedAttribute; struct TranslatedIndexData; struct SourceIndexData; +class ProgramD3D; class InputLayoutCache : angle::NonCopyable { @@ -76,6 +77,14 @@ class InputLayoutCache : angle::NonCopyable uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS]; }; + gl::Error findInputLayout(const PackedAttributeLayout &layout, + unsigned int inputElementCount, + const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS], + ProgramD3D *programD3D, + const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS], + size_t attributeCount, + ID3D11InputLayout **inputLayout); + std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap; ID3D11InputLayout *mCurrentIL; @@ -94,6 +103,6 @@ class InputLayoutCache : angle::NonCopyable D3D_FEATURE_LEVEL mFeatureLevel; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h index adaa9d9acac..f28ce4f8275 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h @@ -44,14 +44,21 @@ typedef IDXGISwapChain DXGISwapChain; typedef IDXGIFactory DXGIFactory; #endif +typedef interface IDCompositionDevice IDCompositionDevice; +typedef interface IDCompositionTarget IDCompositionTarget; +typedef interface IDCompositionVisual IDCompositionVisual; + namespace rx { class NativeWindow { public: - explicit NativeWindow(EGLNativeWindowType window, const egl::Config *config); + explicit NativeWindow(EGLNativeWindowType window, + const egl::Config *config, + bool directComposition); + ~NativeWindow(); bool initialize(); bool getClientRect(LPRECT rect); bool isIconic(); @@ -63,11 +70,17 @@ class NativeWindow inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + void commitChange(); + private: EGLNativeWindowType mWindow; -#if defined(ANGLE_ENABLE_WINDOWS_STORE) + bool mDirectComposition; + IDCompositionDevice *mDevice; + IDCompositionTarget *mCompositionTarget; + IDCompositionVisual *mVisual; const egl::Config *mConfig; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) std::shared_ptr<InspectableNativeWindow> mImpl; #endif diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp index 5678581031d..0ab5980e1ff 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -21,6 +21,7 @@ namespace rx { +using namespace gl_d3d11; template <typename mapType> static void ClearStateMap(mapType &map) @@ -297,14 +298,31 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; } -gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState) +gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState) { if (!mDevice) { return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } - DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); + gl::DepthStencilState glState = originalState; + if (disableDepth) + { + glState.depthTest = false; + glState.depthMask = false; + } + + if (disableStencil) + { + glState.stencilWritemask = 0; + glState.stencilBackWritemask = 0; + glState.stencilTest = false; + } + + auto keyIter = mDepthStencilStateCache.find(glState); if (keyIter != mDepthStencilStateCache.end()) { DepthStencilStateCounterPair &state = keyIter->second; @@ -312,53 +330,55 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &ds *outDSState = state.first; return gl::Error(GL_NO_ERROR); } - else + + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) { - if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) - { - TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " - "to make room.", kMaxDepthStencilStates); + TRACE( + "Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", + kMaxDepthStencilStates); - DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + auto leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } + leastRecentlyUsed = i; } - SafeRelease(leastRecentlyUsed->second.first); - mDepthStencilStateCache.erase(leastRecentlyUsed); } + SafeRelease(leastRecentlyUsed->second.first); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; - dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); - dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); - dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; - dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); - dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); - dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); - dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); - dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); - dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); - dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); - dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); - dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); - dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.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_DEPTH_STENCIL_DESC dsDesc = {0}; + dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask); + dsDesc.DepthFunc = ConvertComparison(glState.depthFunc); + dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask); + dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc); + dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + } - mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + mDepthStencilStateCache.insert( + std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++))); - *outDSState = dx11DepthStencilState; - return gl::Error(GL_NO_ERROR); - } + *outDSState = dx11DepthStencilState; + return gl::Error(GL_NO_ERROR); } std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h index 0099b94a04d..82cb13903cf 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -36,7 +36,10 @@ class RenderStateCache : angle::NonCopyable 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, ID3D11DepthStencilState **outDSState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState); gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); private: diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index ab01482cdfb..c4ca8f39b2e 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -41,6 +41,7 @@ #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/DeviceD3D.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" #include "libANGLE/renderer/d3d/ProgramD3D.h" @@ -194,8 +195,239 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) } } +void SetLineLoopIndices(GLuint *dest, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + dest[i] = static_cast<GLuint>(i); + } + dest[count] = 0; +} + +template <typename T> +void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count) +{ + const T *srcPtr = static_cast<const T *>(indices); + for (size_t i = 0; i < count; ++i) + { + dest[i] = static_cast<GLuint>(srcPtr[i]); + } + dest[count] = static_cast<GLuint>(srcPtr[0]); +} + +void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) +{ + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = 0; + destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1; + destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2; + } +} + +template <typename T> +void CopyLineLoopIndicesWithRestart(const GLvoid *indices, + size_t count, + GLenum indexType, + std::vector<GLuint> *bufferOut) +{ + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex()); + const T *srcPtr = static_cast<const T *>(indices); + Optional<GLuint> currentLoopStart; + + bufferOut->clear(); + + for (size_t indexIdx = 0; indexIdx < count; ++indexIdx) + { + GLuint value = static_cast<GLuint>(srcPtr[indexIdx]); + + if (value == restartIndex) + { + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + bufferOut->push_back(d3dRestartIndex); + currentLoopStart.reset(); + } + } + else + { + bufferOut->push_back(value); + if (!currentLoopStart.valid()) + { + currentLoopStart = value; + } + } + } + + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + } +} + +void GetLineLoopIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector<GLuint> *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + bufferOut->resize(static_cast<size_t>(count) + 1); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetLineLoopIndices(&(*bufferOut)[0], count); + break; + case GL_UNSIGNED_BYTE: + CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count); + break; + default: + UNREACHABLE(); + break; + } +} + +template <typename T> +void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris) +{ + const T *srcPtr = static_cast<const T *>(indices); + + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]); + destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]); + destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]); + } +} + +template <typename T> +void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, + GLuint indexCount, + GLenum indexType, + std::vector<GLuint> *bufferOut) +{ + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT); + const T *srcPtr = static_cast<const T *>(indices); + Optional<GLuint> vertexA; + Optional<GLuint> vertexB; + + bufferOut->clear(); + + for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx) + { + GLuint value = static_cast<GLuint>(srcPtr[indexIdx]); + + if (value == restartIndex) + { + bufferOut->push_back(d3dRestartIndex); + vertexA.reset(); + vertexB.reset(); + } + else + { + if (!vertexA.valid()) + { + vertexA = value; + } + else if (!vertexB.valid()) + { + vertexB = value; + } + else + { + bufferOut->push_back(vertexA.value()); + bufferOut->push_back(vertexB.value()); + bufferOut->push_back(value); + vertexB = value; + } + } + } } +void GetTriFanIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector<GLuint> *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + GLuint numTris = count - 2; + bufferOut->resize(numTris * 3); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetTriangleFanIndices(&(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris); + break; + default: + UNREACHABLE(); + break; + } +} + +} // anonymous namespace + void Renderer11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) { ASSERT(resourceIndex < mCurrentSRVs.size()); @@ -238,6 +470,7 @@ void Renderer11::SRVCache::clear() Renderer11::Renderer11(egl::Display *display) : RendererD3D(display), mStateCache(this), + mStateManager(), mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()), mDebug(nullptr) { @@ -266,6 +499,9 @@ Renderer11::Renderer11(egl::Display *display) mD3d11Module = NULL; mDxgiModule = NULL; + mDCompModule = NULL; + mCreatedWithDeviceEXT = false; + mEGLDevice = nullptr; mDevice = NULL; mDeviceContext = NULL; @@ -284,58 +520,69 @@ Renderer11::Renderer11(egl::Display *display) ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); - const auto &attributes = mDisplay->getAttributeMap(); + if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + 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 = + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinorVersion = + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); + } } - } - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + } } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); } - } - - if (requestedMajorVersion == 9 && requestedMinorVersion == 3) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - } - EGLint requestedDeviceType = 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: - mDriverType = D3D_DRIVER_TYPE_HARDWARE; - break; + EGLint requestedDeviceType = 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: + mDriverType = D3D_DRIVER_TYPE_HARDWARE; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: - mDriverType = D3D_DRIVER_TYPE_WARP; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + mDriverType = D3D_DRIVER_TYPE_WARP; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: - mDriverType = D3D_DRIVER_TYPE_REFERENCE; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDriverType = D3D_DRIVER_TYPE_REFERENCE; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: - mDriverType = D3D_DRIVER_TYPE_NULL; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDriverType = D3D_DRIVER_TYPE_NULL; + break; - default: - UNREACHABLE(); + default: + UNREACHABLE(); + } + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { + mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice()); + ASSERT(mEGLDevice != nullptr); + mCreatedWithDeviceEXT = true; } initializeDebugAnnotator(); @@ -352,68 +599,12 @@ Renderer11::~Renderer11() egl::Error Renderer11::initialize() { -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; - { - SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS"); - TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - - if (mD3d11Module == nullptr || mDxgiModule == nullptr) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_MISSING_DEP, - "Could not load D3D11 or DXGI library."); - } - - // create the D3D11 device - ASSERT(mDevice == nullptr); - D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(GetProcAddress(mD3d11Module, "D3D11CreateDevice")); - - if (D3D11CreateDevice == nullptr) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_MISSING_DEP, - "Could not retrieve D3D11CreateDevice address."); - } - } -#endif - HRESULT result = S_OK; -#ifdef _DEBUG - { - TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)"); - result = D3D11CreateDevice( - NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(), - static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice, - &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); - } - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); - } - - if (!mDevice || FAILED(result)) -#endif + egl::Error error = initializeD3DDevice(); + if (error.isError()) { - SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS"); - TRACE_EVENT0("gpu.angle", "D3D11CreateDevice"); - - result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(), - static_cast<unsigned int>(mAvailableFeatureLevels.size()), - D3D11_SDK_VERSION, &mDevice, - &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); - - // Cleanup done by destructor - if (!mDevice || FAILED(result)) - { - ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", static_cast<int>(result)); - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_CREATEDEVICE_ERROR, - "Could not create D3D11 device."); - } + return error; } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) @@ -562,6 +753,107 @@ egl::Error Renderer11::initialize() return egl::Error(EGL_SUCCESS); } +egl::Error Renderer11::initializeD3DDevice() +{ + HRESULT result = S_OK; + + if (!mCreatedWithDeviceEXT) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS"); + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + mDCompModule = LoadLibrary(TEXT("dcomp.dll")); + + if (mD3d11Module == nullptr || mDxgiModule == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not load D3D11 or DXGI library."); + } + + // create the D3D11 device + ASSERT(mDevice == nullptr); + D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>( + GetProcAddress(mD3d11Module, "D3D11CreateDevice")); + + if (D3D11CreateDevice == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not retrieve D3D11CreateDevice address."); + } + } +#endif + +#ifdef _DEBUG + { + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)"); + result = D3D11CreateDevice( + NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(), + static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, + &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + } + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS"); + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice"); + + result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(), + static_cast<unsigned int>(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &mDevice, + &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + + // Cleanup done by destructor + if (!mDevice || FAILED(result)) + { + ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", + static_cast<int>(result)); + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR, + "Could not create D3D11 device."); + } + } + } + else + { + // We should use the inputted D3D11 device instead + void *device = nullptr; + egl::Error error = mEGLDevice->getDevice(&device); + if (error.isError()) + { + return error; + } + + ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device); + if (FAILED(d3dDevice->GetDeviceRemovedReason())) + { + return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost."); + } + + if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Inputted D3D11 device must be Feature Level 9_3 or greater."); + } + + // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. + mDevice = d3dDevice; + mDevice->AddRef(); + mDevice->GetImmediateContext(&mDeviceContext); + mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); + } + + return egl::Error(EGL_SUCCESS); +} + // do any one-time device initialization // NOTE: this is also needed after a device lost/reset // to reset the scene status and ensure the default states are reset. @@ -600,6 +892,8 @@ void Renderer11::initializeDevice() ASSERT(!mPixelTransfer); mPixelTransfer = new PixelTransfer11(this); + mStateManager.initialize(mDeviceContext, &mStateCache, &mRenderer11DeviceCaps); + const gl::Caps &rendererCaps = getRendererCaps(); mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); @@ -697,6 +991,8 @@ egl::ConfigSet Renderer11::generateConfigs() const const gl::Caps &rendererCaps = getRendererCaps(); const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + const EGLint optimalSurfaceOrientation = EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; + egl::ConfigSet configs; for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) { @@ -751,6 +1047,7 @@ egl::ConfigSet Renderer11::generateConfigs() const config.transparentRedValue = 0; config.transparentGreenValue = 0; config.transparentBlueValue = 0; + config.optimalOrientation = optimalSurfaceOrientation; configs.add(config); } @@ -778,6 +1075,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions outExtensions->querySurfacePointer = true; outExtensions->windowFixedSize = true; + outExtensions->surfaceOrientation = true; // D3D11 does not support present with dirty rectangles until DXGI 1.2. outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; @@ -791,6 +1089,9 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions outExtensions->glTexture2DImage = true; outExtensions->glTextureCubemapImage = true; outExtensions->glRenderbufferImage = true; + + outExtensions->flexibleSurfaceCompatibility = true; + outExtensions->directComposition = !!mDCompModule; } gl::Error Renderer11::flush() @@ -842,9 +1143,14 @@ gl::Error Renderer11::finish() return gl::Error(GL_NO_ERROR); } -SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) { - return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); + return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, + orientation); } void *Renderer11::getD3DDevice() @@ -1124,229 +1430,54 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode) { - if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + // 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()) { - ID3D11RasterizerState *dxRasterState = NULL; - gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState); - if (error.isError()) - { - return error; - } - - mDeviceContext->RSSetState(dxRasterState); - - mCurRasterState = rasterState; + return error; } - mForceSetRasterState = false; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) -{ - if (mForceSetBlendState || - memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || - sampleMask != mCurSampleMask) - { - ID3D11BlendState *dxBlendState = NULL; - gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState); - if (error.isError()) - { - return error; - } - - ASSERT(dxBlendState != NULL); - - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + // Setting viewport state + mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), + data.state->getFarPlane()); - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - } + // Setting scissor state + mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - mForceSetBlendState = false; + // 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); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - if (mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || - stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) + error = mStateManager.setRasterizerState(rasterizer); + if (error.isError()) { - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - ID3D11DepthStencilState *dxDepthStencilState = NULL; - gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState); - if (error.isError()) - { - return error; - } - - ASSERT(dxDepthStencilState); - - // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer - // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops - static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); - static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); - UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); - - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); - - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; + return error; } - mForceSetDepthStencilState = false; - - return gl::Error(GL_NO_ERROR); -} - -void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled) + // Setting blend state + unsigned int mask = GetBlendSampleMask(data, samples); + error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(), + data.state->getBlendColor(), mask); + if (error.isError()) { - if (enabled) - { - D3D11_RECT rect; - rect.left = std::max(0, scissor.x); - rect.top = std::max(0, scissor.y); - rect.right = scissor.x + std::max(0, scissor.width); - rect.bottom = scissor.y + std::max(0, scissor.height); - - mDeviceContext->RSSetScissorRects(1, &rect); - } - - if (enabled != mScissorEnabled) - { - mForceSetRasterState = true; - } - - mCurScissor = scissor; - mScissorEnabled = enabled; + return error; } - mForceSetScissor = false; + // Setting depth stencil state + error = mStateManager.setDepthStencilState(*data.state); + return error; } -void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) +void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) { - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = static_cast<int>(mRenderTargetDesc.width); - actualViewport.height = static_cast<int>(mRenderTargetDesc.height); - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar; - - if (viewportChanged) - { - const gl::Caps& caps = getRendererCaps(); - - int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth); - int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight); - int dxMinViewportBoundsX = -dxMaxViewportBoundsX; - int dxMinViewportBoundsY = -dxMaxViewportBoundsY; - - if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) - { - // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. - dxMaxViewportBoundsX = static_cast<int>(mRenderTargetDesc.width); - dxMaxViewportBoundsY = static_cast<int>(mRenderTargetDesc.height); - dxMinViewportBoundsX = 0; - dxMinViewportBoundsY = 0; - } - - int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); - int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); - int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); - int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); - - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); - dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); - dxViewport.Width = static_cast<float>(dxViewportWidth); - dxViewport.Height = static_cast<float>(dxViewportHeight); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - - mDeviceContext->RSSetViewports(1, &dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - - // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer). - if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) - { - mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width; - mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height; - mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width; - mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height; - } - - mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; - mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; - mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - // Instanced pointsprite emulation requires ViewCoords to be defined in the - // the vertex shader. - mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; - mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; - mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; - mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; - - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - - mVertexConstants.depthRange[0] = actualZNear; - mVertexConstants.depthRange[1] = actualZFar; - mVertexConstants.depthRange[2] = actualZFar - actualZNear; - - mPixelConstants.depthRange[0] = actualZNear; - mPixelConstants.depthRange[1] = actualZFar; - mPixelConstants.depthRange[2] = actualZFar - actualZNear; - } - - mForceSetViewport = false; + mStateManager.syncState(state, bitmask); } bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) @@ -1408,7 +1539,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) // Also extract the render target dimensions and view unsigned int renderTargetWidth = 0; unsigned int renderTargetHeight = 0; - DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; bool missingColorRenderTarget = true; @@ -1426,7 +1556,8 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) // check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) + const gl::Extents &size = colorbuffer->getSize(); + if (size.width == 0 || size.height == 0) { return gl::Error(GL_NO_ERROR); } @@ -1447,7 +1578,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) { renderTargetWidth = renderTarget->getWidth(); renderTargetHeight = renderTarget->getHeight(); - renderTargetFormat = renderTarget->getDXGIFormat(); missingColorRenderTarget = false; } @@ -1487,7 +1617,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) { renderTargetWidth = depthStencilRenderTarget->getWidth(); renderTargetHeight = depthStencilRenderTarget->getHeight(); - renderTargetFormat = depthStencilRenderTarget->getDXGIFormat(); } // Unbind render target SRVs from the shader here to prevent D3D11 warnings. @@ -1500,25 +1629,23 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); } + + unsigned int stencilSize = depthStencil->getStencilSize(); + mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize); } // Apply the render target and depth stencil - if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || + if (!mDepthStencilInitialized || memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 || reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV) { mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; - mForceSetViewport = true; - mForceSetScissor = true; - mForceSetBlendState = true; + mStateManager.setViewportBounds(renderTargetWidth, renderTargetHeight); + mStateManager.forceSetBlendState(); if (!mDepthStencilInitialized) { - mForceSetRasterState = true; + mStateManager.forceSetRasterState(); } for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++) @@ -1526,7 +1653,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]); } mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV); - mRenderTargetDescInitialized = true; mDepthStencilInitialized = true; } @@ -1557,9 +1683,19 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), sourceInfo); } -gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) +gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo, + SourceIndexData *sourceIndexInfo) { - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo); + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, + indexInfo, sourceIndexInfo, + data.state->isPrimitiveRestartEnabled()); if (error.isError()) { return error; @@ -1656,18 +1792,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) gl::Error Renderer11::drawArraysImpl(const gl::Data &data, GLenum mode, GLsizei count, - GLsizei instances, - bool usesPointSize) + GLsizei instances) { - bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; - if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused()) - { - // Since point sprites are generated with a geometry shader, too many vertices will - // be written if transform feedback is active. To work around this, draw only the points - // with the stream out shader and no pixel shader to feed the stream out buffers and then - // draw again with the point sprite geometry shader to rasterize the point sprites. + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - mDeviceContext->PSSetShader(NULL, NULL, 0); + if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused()) + { + // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback + // won't get the correct output. To work around this, draw with *only* the stream out + // first (no pixel shader) to feed the stream out buffers and then draw again with the + // geometry shader + pixel shader to rasterize the primitives. + mDeviceContext->PSSetShader(nullptr, nullptr, 0); if (instances > 0) { @@ -1678,124 +1813,143 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, mDeviceContext->Draw(count, 0); } - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - - rx::ShaderExecutableD3D *pixelExe = NULL; + rx::ShaderExecutableD3D *pixelExe = nullptr; gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); if (error.isError()) { return error; } - // Skip this step if we're doing rasterizer discard. - if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize) + // Skip the draw call if rasterizer discard is enabled (or no fragment shader). + if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard) { - ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader(); - ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); + return gl::Error(GL_NO_ERROR); + } - // Retrieve the point sprite geometry shader - rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); - ID3D11GeometryShader *geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL); - mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); - ASSERT(geometryShader); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); + ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader(); + ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); - if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } + // Retrieve the geometry shader. + rx::ShaderExecutableD3D *geometryExe = nullptr; + error = + programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr); + if (error.isError()) + { + return error; } + ID3D11GeometryShader *geometryShader = + (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL); + mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); + ASSERT(geometryShader); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } return gl::Error(GL_NO_ERROR); } - else if (mode == GL_LINE_LOOP) + + if (mode == GL_LINE_LOOP) { - return drawLineLoop(count, GL_NONE, NULL, 0, NULL); + return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances); } - else if (mode == GL_TRIANGLE_FAN) + + if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); } - else if (instances > 0) + + if (instances > 0) { mDeviceContext->DrawInstanced(count, instances, 0, 0); return gl::Error(GL_NO_ERROR); } + + bool useInstancedPointSpriteEmulation = + programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation; + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } else { - // If the shader is writing to gl_PointSize, then pointsprites are being rendered. - // Emulating instanced point sprites for FL9_3 requires the topology to be - // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. - if (mode == GL_POINTS && useInstancedPointSpriteEmulation) - { - mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } - return gl::Error(GL_NO_ERROR); + mDeviceContext->Draw(count, 0); } + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawElementsImpl(GLenum mode, +gl::Error Renderer11::drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, - const TranslatedIndexData &indexInfo, - GLsizei instances, - bool usesPointSize) + GLsizei instances) { - bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; int minIndex = static_cast<int>(indexInfo.indexRange.start); if (mode == GL_LINE_LOOP) { - return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + return drawLineLoop(data, count, type, indices, &indexInfo, instances); } - else if (mode == GL_TRIANGLE_FAN) + + if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); + return drawTriangleFan(data, count, type, indices, minIndex, instances); } - else if (instances > 0) + + if (instances > 0) { mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); return gl::Error(GL_NO_ERROR); } + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); + if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + { + // The count parameter passed to drawElements represents the total number of instances + // to be rendered. Each instance is referenced by the bound index buffer from the + // the caller. + // + // Indexed pointsprite emulation replicates data for duplicate entries found + // in the index buffer. + // This is not an efficent rendering mechanism and is only used on downlevel renderers + // that do not support geometry shaders. + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } else { - // 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) - { - // The count parameter passed to drawElements represents the total number of instances - // to be rendered. Each instance is referenced by the bound index buffer from the - // the caller. - // - // Indexed pointsprite emulation replicates data for duplicate entries found - // in the index buffer. - // This is not an efficent rendering mechanism and is only used on downlevel renderers - // that do not support geometry shaders. - mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); - return gl::Error(GL_NO_ERROR); - } - else - { - mDeviceContext->DrawIndexed(count, 0, -minIndex); - return gl::Error(GL_NO_ERROR); - } + mDeviceContext->DrawIndexed(count, 0, -minIndex); } + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +gl::Error Renderer11::drawLineLoop(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indexPointer, + const TranslatedIndexData *indexInfo, + int instances) { + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indices = indexPointer; + // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { @@ -1831,7 +1985,11 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); } - const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); + GetLineLoopIndices(indices, type, static_cast<GLuint>(count), + data.state->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()) { @@ -1846,41 +2004,9 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind return error; } - unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); - unsigned int indexBufferOffset = offset; - - 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(); - } + // Copy over the converted index data. + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], + sizeof(GLuint) * mScratchIndexDataBuffer.size()); error = mLineLoopIB->unmapBuffer(); if (error.isError()) @@ -1892,21 +2018,42 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; + mAppliedIBOffset = offset; } - mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); + INT baseVertexLocation = (indexInfo ? -static_cast<int>(indexInfo->indexRange.start) : 0); + UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0); + } + else + { + mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation); + } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +gl::Error Renderer11::drawTriangleFan(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances) { + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indexPointer = indices; + // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { @@ -1920,7 +2067,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - indices = bufferData + offset; + indexPointer = bufferData + offset; } if (!mTriangleFanIB) @@ -1937,21 +2084,25 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 3); - const unsigned int numTris = count - 2; + const GLuint numTris = count - 2; if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); } - const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + GetTriFanIndices(indexPointer, type, count, data.state->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; } - void* mappedMemory = NULL; + void *mappedMemory = nullptr; unsigned int offset; error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); if (error.isError()) @@ -1959,45 +2110,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); - unsigned int indexBufferOffset = offset; - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLushort*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); error = mTriangleFanIB->unmapBuffer(); if (error.isError()) @@ -2009,32 +2122,32 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; + mAppliedIBOffset = offset; } + UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); + if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0); } else { - mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + mDeviceContext->DrawIndexed(indexCount, 0, -minIndex); } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyShaders(gl::Program *program, - const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, - bool transformFeedbackActive) +gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode) { - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); const auto &inputLayout = programD3D->getCachedInputLayout(); ShaderExecutableD3D *vertexExe = NULL; @@ -2044,30 +2157,39 @@ gl::Error Renderer11::applyShaders(gl::Program *program, return error; } + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); if (error.isError()) { return error; } - ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); + 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 if (mCurRasterState.pointDrawMode) + else { geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL); } @@ -2104,6 +2226,7 @@ gl::Error Renderer11::applyShaders(gl::Program *program, } gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, const std::vector<D3DUniform *> &uniformArray) { unsigned int totalRegisterCountVS = 0; @@ -2242,28 +2365,32 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D, mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); } - if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) + const dx_VertexConstants &vertexConstants = mStateManager.getVertexConstants(); + if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) { ASSERT(mDriverConstantBufferVS != nullptr); if (mDriverConstantBufferVS) { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); - memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants, + 16, 0); + memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants)); } } - if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) + const dx_PixelConstants &pixelConstants = mStateManager.getPixelConstants(); + if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) { ASSERT(mDriverConstantBufferPS != nullptr); if (mDriverConstantBufferPS) { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); - memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16, + 0); + memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants)); } } // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary - if (programD3D.usesGeometryShader()) + if (programD3D.usesGeometryShader(drawMode)) { // needed for the point sprite geometry shader if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) @@ -2284,13 +2411,7 @@ void Renderer11::markAllStateDirty() { TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty"); - for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) - { - mAppliedRTVs[rtIndex] = DirtyPointer; - } - mAppliedDSV = DirtyPointer; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; + markRenderTargetStateDirty(); // We reset the current SRV data because it might not be in sync with D3D's state // anymore. For example when a currently used SRV is used as an RTV, D3D silently @@ -2310,11 +2431,11 @@ void Renderer11::markAllStateDirty() mForceSetPixelSamplerStates[fsamplerId] = true; } - mForceSetBlendState = true; - mForceSetRasterState = true; - mForceSetDepthStencilState = true; - mForceSetScissor = true; - mForceSetViewport = true; + mStateManager.forceSetBlendState(); + mStateManager.forceSetDepthStencilState(); + mStateManager.forceSetRasterState(); + mStateManager.forceSetScissorState(); + mStateManager.forceSetViewportState(); mAppliedIB = NULL; mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; @@ -2354,6 +2475,16 @@ void Renderer11::markAllStateDirty() mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; } +void Renderer11::markRenderTargetStateDirty() +{ + for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) + { + mAppliedRTVs[rtIndex] = DirtyPointer; + } + mAppliedDSV = DirtyPointer; + mDepthStencilInitialized = false; +} + void Renderer11::releaseDeviceResources() { mStateCache.clear(); @@ -2442,6 +2573,13 @@ void Renderer11::release() releaseDeviceResources(); + if (!mCreatedWithDeviceEXT) + { + // Only delete the device if the Renderer11 owns it + // Otherwise we should keep it around in case we try to reinitialize the renderer later + SafeDelete(mEGLDevice); + } + SafeRelease(mDxgiFactory); SafeRelease(mDxgiAdapter); @@ -2469,6 +2607,12 @@ void Renderer11::release() mDxgiModule = NULL; } + if (mDCompModule) + { + FreeLibrary(mDCompModule); + mDCompModule = NULL; + } + mCompiler.release(); } @@ -2489,11 +2633,6 @@ bool Renderer11::resetDevice() return true; } -VendorID Renderer11::getVendorId() const -{ - return static_cast<VendorID>(mAdapterDescription.VendorId); -} - std::string Renderer11::getRendererDescription() const { std::ostringstream rendererString; @@ -2661,7 +2800,8 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: // 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); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2712,7 +2852,8 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl // 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); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2763,7 +2904,8 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl:: // 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); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2814,7 +2956,8 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const // 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); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -3018,9 +3161,12 @@ ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) return new ProgramD3D(data, this); } -gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +gl::Error Renderer11::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) { switch (type) { @@ -3036,25 +3182,22 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); } - if (transformFeedbackVaryings.size() > 0) + if (!streamOutVaryings.empty()) { std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; - for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) + soDeclaration.reserve(streamOutVaryings.size()); + + for (const auto &streamOutVarying : streamOutVaryings) { - const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; - GLenum transposedType = gl::TransposeMatrixType(varying.type); - - for (unsigned int j = 0; j < varying.semanticIndexCount; j++) - { - D3D11_SO_DECLARATION_ENTRY entry = { 0 }; - entry.Stream = 0; - entry.SemanticName = varying.semanticName.c_str(); - entry.SemanticIndex = varying.semanticIndex + j; - entry.StartComponent = 0; - entry.ComponentCount = static_cast<BYTE>(gl::VariableColumnCount(transposedType)); - entry.OutputSlot = static_cast<BYTE>((separatedOutputBuffers ? i : 0)); - soDeclaration.push_back(entry); - } + D3D11_SO_DECLARATION_ENTRY entry = {0}; + entry.Stream = 0; + entry.SemanticName = streamOutVarying.semanticName.c_str(); + entry.SemanticIndex = streamOutVarying.semanticIndex; + entry.StartComponent = 0; + entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount); + entry.OutputSlot = static_cast<BYTE>( + (separatedOutputBuffers ? streamOutVarying.outputSlot : 0)); + soDeclaration.push_back(entry); } result = mDevice->CreateGeometryShaderWithStreamOutput( @@ -3107,9 +3250,12 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, +gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) { const char *profileType = NULL; @@ -3152,6 +3298,15 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); + if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "") + { + // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader". + // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*. + // Using the [unroll] directive works around this, as does this D3DCompile flag. + configs.push_back( + CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); + } + D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; ID3DBlob *binary = NULL; @@ -3171,7 +3326,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin } error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + streamOutVaryings, separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -3551,9 +3706,15 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::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 Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, + const gl::Rectangle &drawRectIn, + RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, + GLenum filter, + const gl::Rectangle *scissor, + bool colorBlit, + bool depthBlit, + bool stencilBlit) { // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, // it should never be the case that both color and depth/stencil need to be blitted at @@ -3619,13 +3780,94 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + // From the spec: + // "The actual region taken from the read framebuffer is limited to the intersection of the + // source buffers being transferred, which may include the color buffer selected by the read + // buffer, the depth buffer, and / or the stencil buffer depending on mask." + // This means negative x and y are out of bounds, and not to be read from. We handle this here + // by internally scaling the read and draw rectangles. + gl::Rectangle readRect = readRectIn; + gl::Rectangle drawRect = drawRectIn; + auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) + { + double readToDrawScale = + static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width); + return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale)); + }; + if (readRect.x < 0) + { + int readOffset = -readRect.x; + readRect.x += readOffset; + readRect.width -= readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.x += drawOffset; + drawRect.width -= drawOffset; + } + + auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) + { + double readToDrawScale = + static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height); + return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale)); + }; + if (readRect.y < 0) + { + int readOffset = -readRect.y; + readRect.y += readOffset; + readRect.height -= readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.y += drawOffset; + drawRect.height -= drawOffset; + } + + if (readRect.x1() < 0) + { + int readOffset = -readRect.x1(); + readRect.width += readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.width += drawOffset; + } + + if (readRect.y1() < 0) + { + int readOffset = -readRect.y1(); + readRect.height += readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.height += drawOffset; + } + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); - bool wholeBufferCopy = !scissorNeeded && - readRect.x == 0 && readRect.width == readSize.width && - readRect.y == 0 && readRect.height == readSize.height && - drawRect.x == 0 && drawRect.width == drawSize.width && - drawRect.y == 0 && drawRect.height == drawSize.height; + const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()); + const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat()); + const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + + // 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.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && + (dxgiFormatInfo.greenBits > 0); + colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && + (dxgiFormatInfo.blueBits > 0); + colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && + (dxgiFormatInfo.alphaBits > 0); + + // We only currently support masking off the alpha channel. + bool colorMaskingNeeded = colorMask.alpha; + ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue); + + bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 && + readRect.width == readSize.width && readRect.y == 0 && + readRect.height == readSize.height && drawRect.x == 0 && + drawRect.width == drawSize.width && drawRect.y == 0 && + drawRect.height == drawSize.height; bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; @@ -3636,14 +3878,13 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); gl::Error result(GL_NO_ERROR); if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && - (!(depthBlit || stencilBlit) || wholeBufferCopy)) + !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) { UINT dstX = drawRect.x; UINT dstY = drawRect.y; @@ -3713,9 +3954,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const } else { - GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; + // 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, format, filter); + scissor, destFormatInfo.format, filter, maskOffAlpha); } } @@ -3919,4 +4161,23 @@ gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeSta return gl::Error(GL_NO_ERROR); } +egl::Error Renderer11::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) + { + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice), + EGL_D3D11_DEVICE_ANGLE, EGL_FALSE); + + if (error.isError()) + { + SafeDelete(mEGLDevice); + return error; + } + } + + *device = static_cast<DeviceImpl *>(mEGLDevice); + return egl::Error(EGL_SUCCESS); +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index c0b3964a0d4..8759f8075b2 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -19,6 +19,7 @@ #include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" namespace gl { @@ -110,7 +111,11 @@ class Renderer11 : public RendererD3D gl::Error flush() override; gl::Error finish() override; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; virtual gl::Error generateSwizzle(gl::Texture *texture); virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); @@ -120,36 +125,30 @@ class Renderer11 : public RendererD3D const std::vector<GLint> &vertexUniformBuffers, const std::vector<GLint> &fragmentUniformBuffers) override; - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); + 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 applyShaders(gl::Program *program, - const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, - bool transformFeedbackActive) 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, SourceIndexData *sourceIndexInfo); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo); + gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo, + SourceIndexData *sourceIndexInfo) override; void applyTransformFeedbackBuffers(const gl::State &state) override; virtual void markAllStateDirty(); + void markRenderTargetStateDirty(); // lost device bool testDeviceLost() override; bool testDeviceResettable() override; - VendorID getVendorId() const override; std::string getRendererDescription() const override; DeviceIdentifier getAdapterIdentifier() const override; @@ -186,14 +185,20 @@ class Renderer11 : public RendererD3D ProgramImpl *createProgram(const gl::Program::Data &data) override; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, - ShaderExecutableD3D **outExectuable); - virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations virtual ImageD3D *createImage(); @@ -236,6 +241,8 @@ class Renderer11 : public RendererD3D ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }; DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + RenderStateCache &getStateCache() { return mStateCache; } + Blit11 *getBlitter() { return mBlit; } Clear11 *getClearer() { return mClear; } @@ -270,24 +277,27 @@ class Renderer11 : public RendererD3D void onSwap(); 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; + + void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; private: gl::Error drawArraysImpl(const gl::Data &data, GLenum mode, GLsizei count, - GLsizei instances, - bool usesPointSize) override; - gl::Error drawElementsImpl(GLenum mode, + GLsizei instances) override; + gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, - const TranslatedIndexData &indexInfo, - GLsizei instances, - bool usesPointSize) override; + GLsizei instances) override; void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions, @@ -295,8 +305,18 @@ class Renderer11 : public RendererD3D WorkaroundsD3D generateWorkarounds() const override; - gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + gl::Error drawLineLoop(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + const TranslatedIndexData *indexInfo, + int instances); + gl::Error drawTriangleFan(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex &index); @@ -307,11 +327,15 @@ class Renderer11 : public RendererD3D HMODULE mD3d11Module; HMODULE mDxgiModule; + HMODULE mDCompModule; std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels; D3D_DRIVER_TYPE mDriverType; + bool mCreatedWithDeviceEXT; + DeviceD3D *mEGLDevice; HLSLCompiler mCompiler; + egl::Error initializeD3DDevice(); void initializeDevice(); void releaseDeviceResources(); void release(); @@ -322,15 +346,6 @@ class Renderer11 : public RendererD3D uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; uintptr_t mAppliedDSV; bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - - struct RenderTargetDesc - { - size_t width; - size_t height; - DXGI_FORMAT format; - }; - RenderTargetDesc mRenderTargetDesc; // Currently applied sampler states std::vector<bool> mForceSetVertexSamplerStates; @@ -382,32 +397,7 @@ class Renderer11 : public RendererD3D // A block of NULL pointers, cached so we don't re-allocate every draw call std::vector<ID3D11ShaderResourceView*> mNullSRVs; - // Currently applied blend state - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - unsigned int mCurSampleMask; - - // Currently applied rasterizer state - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - // Currently applied depth stencil state - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - - // Currently applied scissor rectangle - bool mForceSetScissor; - bool mScissorEnabled; - gl::Rectangle mCurScissor; - - // Currently applied viewport - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; + StateManager11 mStateManager; // Currently applied primitive topology D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; @@ -434,7 +424,6 @@ class Renderer11 : public RendererD3D uintptr_t mAppliedGeometryShader; uintptr_t mAppliedPixelShader; - dx_VertexConstants mVertexConstants; dx_VertexConstants mAppliedVertexConstants; ID3D11Buffer *mDriverConstantBufferVS; ID3D11Buffer *mCurrentVertexConstantBuffer; @@ -442,7 +431,6 @@ class Renderer11 : public RendererD3D GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; - dx_PixelConstants mPixelConstants; dx_PixelConstants mAppliedPixelConstants; ID3D11Buffer *mDriverConstantBufferPS; ID3D11Buffer *mCurrentPixelConstantBuffer; @@ -487,6 +475,8 @@ class Renderer11 : public RendererD3D char mDescription[128]; DXGIFactory *mDxgiFactory; ID3D11Debug *mDebug; + + std::vector<GLuint> mScratchIndexDataBuffer; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp new file mode 100644 index 00000000000..7351c2ad0c0 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -0,0 +1,582 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager11.cpp: Defines a class for caching D3D11 state + +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" + +#include "common/BitSetIterator.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +StateManager11::StateManager11() + : mBlendStateIsDirty(false), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mDepthStencilStateIsDirty(false), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurStencilSize(0), + mRasterizerStateIsDirty(false), + mScissorStateIsDirty(false), + mCurScissorEnabled(false), + mCurScissorRect(), + mViewportStateIsDirty(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mViewportBounds(), + mRenderer11DeviceCaps(nullptr), + mDeviceContext(nullptr), + mStateCache(nullptr) +{ + mCurBlendState.blend = false; + mCurBlendState.sourceBlendRGB = GL_ONE; + mCurBlendState.destBlendRGB = GL_ZERO; + mCurBlendState.sourceBlendAlpha = GL_ONE; + mCurBlendState.destBlendAlpha = GL_ZERO; + mCurBlendState.blendEquationRGB = GL_FUNC_ADD; + mCurBlendState.blendEquationAlpha = GL_FUNC_ADD; + mCurBlendState.colorMaskRed = true; + mCurBlendState.colorMaskBlue = true; + mCurBlendState.colorMaskGreen = true; + mCurBlendState.colorMaskAlpha = true; + mCurBlendState.sampleAlphaToCoverage = false; + mCurBlendState.dither = false; + + mCurDepthStencilState.depthTest = false; + mCurDepthStencilState.depthFunc = GL_LESS; + mCurDepthStencilState.depthMask = true; + mCurDepthStencilState.stencilTest = false; + mCurDepthStencilState.stencilMask = true; + mCurDepthStencilState.stencilFail = GL_KEEP; + mCurDepthStencilState.stencilPassDepthFail = GL_KEEP; + mCurDepthStencilState.stencilPassDepthPass = GL_KEEP; + mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1); + mCurDepthStencilState.stencilBackFunc = GL_ALWAYS; + mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1); + mCurDepthStencilState.stencilBackFail = GL_KEEP; + mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP; + mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP; + mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1); + + mCurRasterState.rasterizerDiscard = false; + mCurRasterState.cullFace = false; + mCurRasterState.cullMode = GL_BACK; + mCurRasterState.frontFace = GL_CCW; + mCurRasterState.polygonOffsetFill = false; + mCurRasterState.polygonOffsetFactor = 0.0f; + mCurRasterState.polygonOffsetUnits = 0.0f; + mCurRasterState.pointDrawMode = false; + mCurRasterState.multiSample = false; +} + +StateManager11::~StateManager11() +{ +} + +void StateManager11::initialize(ID3D11DeviceContext *deviceContext, + RenderStateCache *stateCache, + Renderer11DeviceCaps *renderer11DeviceCaps) +{ + mDeviceContext = deviceContext; + mStateCache = stateCache; + mRenderer11DeviceCaps = renderer11DeviceCaps; +} + +void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mDepthStencilStateIsDirty = true; + } +} + +void StateManager11::setViewportBounds(const int width, const int height) +{ + if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3 && + (mViewportBounds.width != width || mViewportBounds.height != height)) + { + mViewportBounds = gl::Extents(width, height, 1); + mViewportStateIsDirty = true; + } +} + +void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || + blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_FUNCS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || + blendState.destBlendRGB != mCurBlendState.destBlendRGB || + blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || + blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_COLOR_MASK: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || + blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || + blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || + blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc || + depthStencil.stencilMask != mCurDepthStencilState.stencilMask || + state.getStencilRef() != mCurStencilRef) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || + depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || + state.getStencilBackRef() != mCurStencilBackRef) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail || + depthStencil.stencilPassDepthFail != + mCurDepthStencilState.stencilPassDepthFail || + depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail || + depthStencil.stencilBackPassDepthFail != + mCurDepthStencilState.stencilBackPassDepthFail || + depthStencil.stencilBackPassDepthPass != + mCurDepthStencilState.stencilBackPassDepthPass) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterState = state.getRasterizerState(); + if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mRasterizerStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: + if (state.getRasterizerState().rasterizerDiscard != + mCurRasterState.rasterizerDiscard) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mScissorStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mScissorStateIsDirty = true; + // Rasterizer state update needs mCurScissorsEnabled and updates when it changes + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mViewportStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mViewportStateIsDirty = true; + } + break; + default: + break; + } + } +} + +gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + if (!mBlendStateIsDirty && sampleMask == mCurSampleMask) + { + return gl::Error(GL_NO_ERROR); + } + + ID3D11BlendState *dxBlendState = nullptr; + gl::Error error = mStateCache->getBlendState(framebuffer, blendState, &dxBlendState); + if (error.isError()) + { + return error; + } + + ASSERT(dxBlendState != nullptr); + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && + blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + + mBlendStateIsDirty = false; + + return error; +} + +gl::Error StateManager11::setDepthStencilState(const gl::State &glState) +{ + const auto &fbo = *glState.getDrawFramebuffer(); + + // Disable the depth test/depth write if we are using a stencil-only attachment. + // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read + // nor write to the unused depth part of this emulated texture. + bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil()); + + // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. + bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil()); + + // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. + if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && + disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && + disableStencil == mCurDisableStencil.value()) + { + return gl::Error(GL_NO_ERROR); + } + + const auto &depthStencilState = glState.getDepthStencilState(); + int stencilRef = glState.getStencilRef(); + int stencilBackRef = glState.getStencilBackRef(); + + // get the maximum size of the stencil ref + unsigned int maxStencil = 0; + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + maxStencil = (1 << mCurStencilSize) - 1; + } + ASSERT((depthStencilState.stencilWritemask & maxStencil) == + (depthStencilState.stencilBackWritemask & maxStencil)); + ASSERT(stencilRef == stencilBackRef); + ASSERT((depthStencilState.stencilMask & maxStencil) == + (depthStencilState.stencilBackMask & maxStencil)); + + ID3D11DepthStencilState *dxDepthStencilState = NULL; + gl::Error error = mStateCache->getDepthStencilState(depthStencilState, disableDepth, + disableStencil, &dxDepthStencilState); + if (error.isError()) + { + return error; + } + + ASSERT(dxDepthStencilState); + + // Max D3D11 stencil reference value is 0xFF, + // corresponding to the max 8 bits in a stencil buffer + // GL specifies we should clamp the ref value to the + // nearest bit depth when doing stencil ops + static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, + "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); + static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, + "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); + UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurDisableDepth = disableDepth; + mCurDisableStencil = disableStencil; + + mDepthStencilStateIsDirty = false; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (!mRasterizerStateIsDirty) + { + return gl::Error(GL_NO_ERROR); + } + + ID3D11RasterizerState *dxRasterState = nullptr; + gl::Error error = + mStateCache->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState); + if (error.isError()) + { + return error; + } + + mDeviceContext->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + mRasterizerStateIsDirty = false; + + return error; +} + +void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (!mScissorStateIsDirty) + return; + + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, scissor.y); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = scissor.y + std::max(0, scissor.height); + + mDeviceContext->RSSetScissorRects(1, &rect); + } + + mCurScissorRect = scissor; + mCurScissorEnabled = enabled; + mScissorStateIsDirty = false; +} + +void StateManager11::setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar) +{ + if (!mViewportStateIsDirty) + return; + + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth); + int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight); + int dxMinViewportBoundsX = -dxMaxViewportBoundsX; + int dxMinViewportBoundsY = -dxMaxViewportBoundsY; + + if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. + dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width); + dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height); + dxMinViewportBoundsX = 0; + dxMinViewportBoundsY = 0; + } + + int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); + int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); + int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); + dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); + dxViewport.Width = static_cast<float>(dxViewportWidth); + dxViewport.Height = static_cast<float>(dxViewportHeight); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + mDeviceContext->RSSetViewports(1, &dxViewport); + + mCurViewport = viewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders + // using viewAdjust (like the D3D9 renderer). + if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) + + 2 * (viewport.x - dxViewportTopLeftX)) / + dxViewport.Width; + mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) + + 2 * (viewport.y - dxViewportTopLeftY)) / + dxViewport.Height; + mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width; + mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height; + } + + mPixelConstants.viewCoords[0] = viewport.width * 0.5f; + mPixelConstants.viewCoords[1] = viewport.height * 0.5f; + mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f); + mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f); + + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; + mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; + mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; + mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; + + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + + mVertexConstants.depthRange[0] = actualZNear; + mVertexConstants.depthRange[1] = actualZFar; + mVertexConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.depthRange[0] = actualZNear; + mPixelConstants.depthRange[1] = actualZFar; + mPixelConstants.depthRange[2] = actualZFar - actualZNear; + + mViewportStateIsDirty = false; +} + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h new file mode 100644 index 00000000000..b432c9d9ef3 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -0,0 +1,107 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager11.h: Defines a class for caching D3D11 state + +#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ +#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Data.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +struct RenderTargetDesc; +struct Renderer11DeviceCaps; + +class StateManager11 final : angle::NonCopyable +{ + public: + StateManager11(); + ~StateManager11(); + + void initialize(ID3D11DeviceContext *deviceContext, + RenderStateCache *stateCache, + Renderer11DeviceCaps *renderer11DeviceCaps); + + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + + gl::Error setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask); + + gl::Error setDepthStencilState(const gl::State &glState); + + gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + + void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar); + + void forceSetBlendState() { mBlendStateIsDirty = true; } + void forceSetDepthStencilState() { mDepthStencilStateIsDirty = true; } + void forceSetRasterState() { mRasterizerStateIsDirty = true; } + void forceSetScissorState() { mScissorStateIsDirty = true; } + void forceSetViewportState() { mViewportStateIsDirty = true; } + void setViewportBounds(const int width, const int height); + + const dx_VertexConstants &getVertexConstants() const { return mVertexConstants; } + const dx_PixelConstants &getPixelConstants() const { return mPixelConstants; } + + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + private: + // Blend State + bool mBlendStateIsDirty; + // TODO(dianx) temporary representation of a dirty bit. once we move enough states in, + // try experimenting with dirty bit instead of a bool + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied depth stencil state + bool mDepthStencilStateIsDirty; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + unsigned int mCurStencilSize; + Optional<bool> mCurDisableDepth; + Optional<bool> mCurDisableStencil; + + // Currenly applied rasterizer state + bool mRasterizerStateIsDirty; + gl::RasterizerState mCurRasterState; + + // Currently applied scissor rectangle state + bool mScissorStateIsDirty; + bool mCurScissorEnabled; + gl::Rectangle mCurScissorRect; + + // Currently applied viewport state + bool mViewportStateIsDirty; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Things needed in viewport state + dx_VertexConstants mVertexConstants; + dx_PixelConstants mPixelConstants; + + // Render target variables + gl::Extents mViewportBounds; + + Renderer11DeviceCaps *mRenderer11DeviceCaps; + ID3D11DeviceContext *mDeviceContext; + RenderStateCache *mStateCache; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index 8a4b6199d18..b6c9c667610 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -8,6 +8,8 @@ #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include <EGL/eglext.h> + #include "libANGLE/features.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" @@ -29,40 +31,43 @@ namespace rx { -SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChain11::SwapChain11(Renderer11 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mOrientation(orientation), + mAppCreatedShareHandle(mShareHandle != nullptr), + mSwapInterval(0), mPassThroughResourcesInit(false), + mFirstSwap(true), + mSwapChain(nullptr), + mSwapChain1(nullptr), + mKeyedMutex(nullptr), + mBackBufferTexture(nullptr), + mBackBufferRTView(nullptr), + mBackBufferSRView(nullptr), + mNeedsOffscreenTexture(orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE), + mOffscreenTexture(nullptr), + mOffscreenRTView(nullptr), + mOffscreenSRView(nullptr), + mDepthStencilTexture(nullptr), + mDepthStencilDSView(nullptr), + mDepthStencilSRView(nullptr), + mQuadVB(nullptr), + mPassThroughSampler(nullptr), + mPassThroughIL(nullptr), + mPassThroughVS(nullptr), + mPassThroughPS(nullptr), + mPassThroughRS(nullptr), mColorRenderTarget(this, renderer, false), mDepthStencilRenderTarget(this, renderer, true) { - mHeight = -1; - mWidth = -1; - mAppCreatedShareHandle = mShareHandle != NULL; - mSwapInterval = 0; - - mSwapChain = NULL; - mSwapChain1 = nullptr; - - mKeyedMutex = nullptr; - - mBackBufferTexture = NULL; - mBackBufferRTView = NULL; - - mOffscreenTexture = NULL; - mOffscreenRTView = NULL; - mOffscreenSRView = NULL; - - mDepthStencilTexture = NULL; - mDepthStencilDSView = NULL; - mDepthStencilSRView = NULL; - - mQuadVB = NULL; - mPassThroughSampler = NULL; - mPassThroughIL = NULL; - mPassThroughVS = NULL; - mPassThroughPS = NULL; } SwapChain11::~SwapChain11() @@ -77,6 +82,7 @@ void SwapChain11::release() SafeRelease(mKeyedMutex); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); SafeRelease(mOffscreenTexture); SafeRelease(mOffscreenRTView); SafeRelease(mOffscreenSRView); @@ -88,6 +94,7 @@ void SwapChain11::release() SafeRelease(mPassThroughIL); SafeRelease(mPassThroughVS); SafeRelease(mPassThroughPS); + SafeRelease(mPassThroughRS); if (!mAppCreatedShareHandle) { @@ -95,18 +102,47 @@ void SwapChain11::release() } } -void SwapChain11::releaseOffscreenTexture() +void SwapChain11::releaseOffscreenColorBuffer() { SafeRelease(mOffscreenTexture); SafeRelease(mOffscreenRTView); SafeRelease(mOffscreenSRView); +} + +void SwapChain11::releaseOffscreenDepthBuffer() +{ SafeRelease(mDepthStencilTexture); SafeRelease(mDepthStencilDSView); SafeRelease(mDepthStencilSRView); } -EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight) { + if (mNeedsOffscreenTexture) + { + EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) +{ + ASSERT(mNeedsOffscreenTexture); + TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); @@ -125,7 +161,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei const int previousWidth = mWidth; const int previousHeight = mHeight; - releaseOffscreenTexture(); + releaseOffscreenColorBuffer(); const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); @@ -230,7 +266,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture); } - D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; @@ -250,10 +285,41 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); - const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + if (previousOffscreenTexture != nullptr) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, backbufferWidth); + sourceBox.top = std::max(previousHeight - backbufferHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(backbufferHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, + previousOffscreenTexture, 0, &sourceBox); + + SafeRelease(previousOffscreenTexture); + + if (mSwapChain) + { + swapRect(0, 0, backbufferWidth, backbufferHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight) +{ + releaseOffscreenDepthBuffer(); if (mDepthBufferFormat != GL_NONE) { + const d3d11::TextureFormat &depthBufferFormatInfo = + d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; depthStencilTextureDesc.Width = backbufferWidth; depthStencilTextureDesc.Height = backbufferHeight; @@ -273,7 +339,9 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei depthStencilTextureDesc.CPUAccessFlags = 0; depthStencilTextureDesc.MiscFlags = 0; - result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = + device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); if (FAILED(result)) { ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); @@ -314,31 +382,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } } - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - if (previousOffscreenTexture != NULL) - { - D3D11_BOX sourceBox = {0}; - sourceBox.left = 0; - sourceBox.right = std::min(previousWidth, mWidth); - sourceBox.top = std::max(previousHeight - mHeight, 0); - sourceBox.bottom = previousHeight; - sourceBox.front = 0; - sourceBox.back = 1; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const int yoffset = std::max(mHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); - - SafeRelease(previousOffscreenTexture); - - if (mSwapChain) - { - swapRect(0, 0, mWidth, mHeight); - } - } - return EGL_SUCCESS; } @@ -358,11 +401,18 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_SUCCESS; } + // Don't resize unnecessarily + if (mWidth == backbufferWidth && mHeight == backbufferHeight) + { + return EGL_SUCCESS; + } + // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); // Resize swap chain DXGI_SWAP_CHAIN_DESC desc; @@ -398,14 +448,22 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) 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"); + } - 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"); + } } - return resetOffscreenTexture(backbufferWidth, backbufferHeight); + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); } DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const @@ -417,6 +475,20 @@ DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) { + mSwapInterval = static_cast<unsigned int>(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] + // range + return EGL_BAD_PARAMETER; + } + + // If the swap chain already exists, just resize + if (mSwapChain != nullptr) + { + return resize(backbufferWidth, backbufferHeight); + } + TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); @@ -432,17 +504,10 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); - mSwapInterval = static_cast<unsigned int>(swapInterval); - if (mSwapInterval > 4) - { - // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range - return EGL_BAD_PARAMETER; - } - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) { - releaseOffscreenTexture(); + releaseOffscreenColorBuffer(); return EGL_SUCCESS; } @@ -479,9 +544,15 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); } - return resetOffscreenTexture(backbufferWidth, backbufferHeight); + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); } void SwapChain11::initPassThroughResources() @@ -549,12 +620,50 @@ void SwapChain11::initPassThroughResources() ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); + // Use the default rasterizer state but without culling + D3D11_RASTERIZER_DESC rasterizerDesc; + rasterizerDesc.FillMode = D3D11_FILL_SOLID; + rasterizerDesc.CullMode = D3D11_CULL_NONE; + rasterizerDesc.FrontCounterClockwise = FALSE; + rasterizerDesc.DepthBias = 0; + rasterizerDesc.SlopeScaledDepthBias = 0.0f; + rasterizerDesc.DepthBiasClamp = 0.0f; + rasterizerDesc.DepthClipEnable = TRUE; + rasterizerDesc.ScissorEnable = FALSE; + rasterizerDesc.MultisampleEnable = FALSE; + rasterizerDesc.AntialiasedLineEnable = FALSE; + result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state"); + mPassThroughResourcesInit = true; } // parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { + if (mNeedsOffscreenTexture) + { + EGLint result = copyOffscreenToBackbuffer(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = present(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + + mRenderer->onSwap(); + + return EGL_SUCCESS; +} + +EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ if (!mSwapChain) { return EGL_SUCCESS; @@ -562,7 +671,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) initPassThroughResources(); - ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices @@ -586,6 +694,16 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); + // Invert the quad vertices depending on the surface orientation. + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) + { + std::swap(x1, x2); + } + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0) + { + std::swap(y1, y2); + } + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); @@ -603,7 +721,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); - deviceContext->RSSetState(NULL); + deviceContext->RSSetState(mPassThroughRS); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); @@ -640,28 +758,54 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); + return EGL_SUCCESS; +} + +EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + UINT swapInterval = mSwapInterval; #if ANGLE_VSYNC == ANGLE_DISABLED - result = mSwapChain->Present(0, 0); -#else + swapInterval = 0; +#endif + + HRESULT result = S_OK; + // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. if (mSwapChain1 != nullptr) { - RECT rect = + if (mFirstSwap) { - static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), - static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y) - }; - DXGI_PRESENT_PARAMETERS params = { 1, &rect, nullptr, nullptr }; - result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); + // Can't swap with a dirty rect if this swap chain has never swapped before + DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } + else + { + RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), + static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)}; + DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } } else { - result = mSwapChain->Present(mSwapInterval, 0); + result = mSwapChain->Present(swapInterval, 0); } -#endif + + mFirstSwap = false; + + // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render + // target. Mark it dirty. + mRenderer->markRenderTargetStateDirty(); if (result == DXGI_ERROR_DEVICE_REMOVED) { + ID3D11Device *device = mRenderer->getDevice(); HRESULT removedReason = device->GetDeviceRemovedReason(); UNUSED_TRACE_VARIABLE(removedReason); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); @@ -677,24 +821,24 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) ERR("Present failed with error code 0x%08X", result); } - mRenderer->onSwap(); + mNativeWindow.commitChange(); return EGL_SUCCESS; } ID3D11Texture2D *SwapChain11::getOffscreenTexture() { - return mOffscreenTexture; + return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture; } ID3D11RenderTargetView *SwapChain11::getRenderTarget() { - return mOffscreenRTView; + return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView; } ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() { - return mOffscreenSRView; + return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView; } ID3D11DepthStencilView *SwapChain11::getDepthStencil() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h index 24c21e10e8c..583e29c3c81 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -20,8 +20,12 @@ class Renderer11; class SwapChain11 : public SwapChainD3D { public: - SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChain11(Renderer11 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); virtual ~SwapChain11(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); @@ -47,24 +51,36 @@ class SwapChain11 : public SwapChainD3D private: void release(); void initPassThroughResources(); - void releaseOffscreenTexture(); - EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); + + void releaseOffscreenColorBuffer(); + void releaseOffscreenDepthBuffer(); + EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight); + DXGI_FORMAT getSwapChainNativeFormat() const; + EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height); + EGLint present(EGLint x, EGLint y, EGLint width, EGLint height); + Renderer11 *mRenderer; - EGLint mHeight; EGLint mWidth; + EGLint mHeight; + const EGLint mOrientation; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; + bool mFirstSwap; DXGISwapChain *mSwapChain; IDXGISwapChain1 *mSwapChain1; IDXGIKeyedMutex *mKeyedMutex; ID3D11Texture2D *mBackBufferTexture; ID3D11RenderTargetView *mBackBufferRTView; + ID3D11ShaderResourceView *mBackBufferSRView; + const bool mNeedsOffscreenTexture; ID3D11Texture2D *mOffscreenTexture; ID3D11RenderTargetView *mOffscreenRTView; ID3D11ShaderResourceView *mOffscreenSRView; @@ -78,6 +94,7 @@ class SwapChain11 : public SwapChainD3D ID3D11InputLayout *mPassThroughIL; ID3D11VertexShader *mPassThroughVS; ID3D11PixelShader *mPassThroughPS; + ID3D11RasterizerState *mPassThroughRS; SurfaceRenderTarget11 mColorRenderTarget; SurfaceRenderTarget11 mDepthStencilRenderTarget; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp index 42b1b3b6585..580a59cf144 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -554,8 +554,9 @@ 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); + return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, + NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format, + GL_LINEAR, false); } void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) @@ -649,7 +650,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image 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); + 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); @@ -669,8 +673,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image // TODO: fast path LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); - loadFunction(width, height, depth, - pixelData, srcRowPitch, srcDepthPitch, + loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, srcDepthPitch, conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); @@ -2223,7 +2226,7 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py new file mode 100644 index 00000000000..0985ba8c687 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py @@ -0,0 +1,199 @@ +#!/usr/bin/python +# Copyright 2015 The ANGLE Project Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# gen_load_functions_table.py: +# Code generation for the load function tables used for texture formats +# + +import json + +template = """// 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/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, LoadImageFunction> &GetLoadFunctionsMap(GLenum {internal_format}, + DXGI_FORMAT {dxgi_format}) +{{ + // clang-format off + switch ({internal_format}) + {{ +{data} + default: + {{ + static std::map<GLenum, LoadImageFunction> emptyLoadFunctionsMap; + return emptyLoadFunctionsMap; + }} + }} + // clang-format on + +}} // GetLoadFunctionsMap + +}} // namespace d3d11 + +}} // namespace rx +""" + +internal_format_param = 'internalFormat' +dxgi_format_param = 'dxgiFormat' +dxgi_format_unknown = "DXGI_FORMAT_UNKNOWN" + +def get_function_maps_string(typestr, function): + return ' loadMap[' + typestr + '] = ' + function + ';\n' + +def get_unknown_format_string(dxgi_to_type_map, dxgi_unknown_string): + if dxgi_unknown_string not in dxgi_to_type_map: + return '' + + table_data = '' + + for unknown_type_function in dxgi_to_type_map[dxgi_unknown_string]: + table_data += get_function_maps_string(unknown_type_function['type'], unknown_type_function['loadFunction']) + + return table_data + +# Making map from dxgi to type map for a particular internalFormat +def create_dxgi_to_type_map(dst, json_data, internal_format_str): + for type_item in sorted(json_data[internal_format_str].iteritems()): + for entry_in_type_item in type_item[1]: + dxgi_format_str = entry_in_type_item['dxgiFormat'] + + if dxgi_format_str not in dst: + dst[dxgi_format_str] = [] + + type_dxgi_load_function = entry_in_type_item.copy(); + type_dxgi_load_function['type'] = type_item[0] + dst[dxgi_format_str].append(type_dxgi_load_function) + +def get_load_function_map_snippet(insert_map_string): + load_function_map_snippet = '' + load_function_map_snippet += ' static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {\n' + load_function_map_snippet += ' std::map<GLenum, LoadImageFunction> loadMap;\n' + load_function_map_snippet += insert_map_string + load_function_map_snippet += ' return loadMap;\n' + load_function_map_snippet += ' }();\n\n' + load_function_map_snippet += ' return loadFunctionsMap;\n' + + return load_function_map_snippet + +def parse_json_into_switch_string(json_data): + table_data = '' + for internal_format_item in sorted(json_data.iteritems()): + internal_format_str = internal_format_item[0] + table_data += ' case ' + internal_format_str + ':\n' + table_data += ' {\n' + table_data += ' switch (' + dxgi_format_param + ')\n' + table_data += ' {\n' + + dxgi_to_type_map = {}; + create_dxgi_to_type_map(dxgi_to_type_map, json_data, internal_format_str) + + dxgi_unknown_str = get_unknown_format_string(dxgi_to_type_map, dxgi_format_unknown); + + for dxgi_format_item in sorted(dxgi_to_type_map.iteritems()): + dxgi_format_str = dxgi_format_item[0] + + # Main case statements + table_data += ' case ' + dxgi_format_str + ':\n' + table_data += ' {\n' + insert_map_string = '' + types_already_in_loadmap = set() + for type_function in sorted(dxgi_format_item[1]): + # type_function['requiresConversion'] element is not in use at the moment but may be needed later + insert_map_string += get_function_maps_string(type_function['type'], type_function['loadFunction']) + types_already_in_loadmap.add(type_function['type']) + + # DXGI_FORMAT_UNKNOWN add ons + if dxgi_format_unknown in dxgi_to_type_map: + for unknown_type_function in dxgi_to_type_map[dxgi_format_unknown]: + # Check that it's not already in the loadmap so it doesn't override the value + if unknown_type_function['type'] not in types_already_in_loadmap: + insert_map_string += get_function_maps_string(unknown_type_function['type'], unknown_type_function['loadFunction']) + + table_data += get_load_function_map_snippet(insert_map_string) + table_data += ' }\n' + + table_data += ' default:\n' + + if dxgi_unknown_str: + table_data += ' {\n' + table_data += get_load_function_map_snippet(dxgi_unknown_str) + table_data += ' }\n' + else: + table_data += ' break;\n' + table_data += ' }\n' + table_data += ' }\n' + + return table_data + +with open('load_functions_data.json') as functions_json_file: + functions_data = functions_json_file.read(); + functions_json_file.close() + json_data = json.loads(functions_data) + + table_data = parse_json_into_switch_string(json_data) + output = template.format(internal_format = internal_format_param, + dxgi_format = dxgi_format_param, + data=table_data) + + with open('load_functions_table_autogen.cpp', 'wt') as out_file: + out_file.write(output) + out_file.close() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py new file mode 100644 index 00000000000..212b19edd16 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py @@ -0,0 +1,133 @@ +#!/usr/bin/python +# Copyright 2015 The ANGLE Project Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# gen_swizzle_format_table.py: +# Code generation for the swizzle format table used for texture formats +# + +import json +import pprint + +template = """// 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 ({component_type_param}) + {{ +{data} + default: + {{ + static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return defaultInfo; + }} + }} + // clang-format on + +}} // GetSwizzleFormatInfo + +}} // namespace d3d11 + +}} // namespace rx +""" + +max_bits_param = 'maxBits' +component_type_param = 'componentType' + +tex_format_key = 'texFormat' +srv_format_key = 'srvFormat' +rtv_format_key = 'rtvFormat' + + +def parse_json_into_switch_string(json_data): + table_data = '' + for component_type in sorted(json_data.iteritems()): + type_str = component_type[0] + table_data += ' case ' + type_str + ':\n' + table_data += ' {\n' + + table_data += ' switch (' + max_bits_param + ')\n' + table_data += ' {\n' + + for max_width_item in sorted(json_data[type_str].iteritems()): + max_width = max_width_item[0] + table_data += ' case ' + max_width + ':\n' + table_data += ' {\n' + table_data += ' static const SwizzleFormatInfo formatInfo(' + json_data[type_str][max_width][tex_format_key] + ',\n' + table_data += ' ' + json_data[type_str][max_width][srv_format_key] + ',\n' + table_data += ' ' + json_data[type_str][max_width][rtv_format_key] + ');\n' + table_data += ' return formatInfo;\n' + + table_data += ' }\n' + table_data += ' default:\n' + table_data += ' break;\n' + table_data += ' }\n' + table_data += ' }\n' + + return table_data + +with open('swizzle_format_data.json') as functions_json_file: + functions_data = functions_json_file.read(); + functions_json_file.close() + json_data = json.loads(functions_data) + + table_data = parse_json_into_switch_string(json_data) + output = template.format(component_type_param=component_type_param, + data=table_data) + + with open('swizzle_format_info_autogen.cpp', 'wt') as out_file: + out_file.write(output) + out_file.close() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py new file mode 100644 index 00000000000..d0ad86b62ed --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py @@ -0,0 +1,303 @@ +#!/usr/bin/python +# Copyright 2015 The ANGLE Project Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# gen_texture_format_table.py: +# Code generation for texture format map +# + +import json +import pprint + +template = """// 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. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// texture_format_table: +// Queries for full textureFormat information based in internalFormat +// + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "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" + +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) +{{ + // clang-format off + switch (internalFormat) + {{ +{data} + default: + break; + }} + // clang-format on + + static const TextureFormat defaultInfo; + return defaultInfo; +}} // GetTextureFormatInfo + +}} // namespace d3d11 + +}} // namespace rx +""" + +def get_texture_format_item(idx, texture_format): + table_data = ''; + + tex_format = texture_format["texFormat"] if "texFormat" in texture_format else "DXGI_FORMAT_UNKNOWN" + srv_format = texture_format["srvFormat"] if "srvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN" + rtv_format = texture_format["rtvFormat"] if "rtvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN" + dsv_format = texture_format["dsvFormat"] if "dsvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN" + requirements_fn = texture_format["requirementsFcn"] if "requirementsFcn" in texture_format else "AnyDevice" + + if idx == 0: + table_data += ' if (' + requirements_fn + '(renderer11DeviceCaps))\n' + else: + table_data += ' else if (' + requirements_fn + '(renderer11DeviceCaps))\n' + table_data += ' {\n' + table_data += ' static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,\n' + table_data += ' ' + tex_format + ',\n' + table_data += ' ' + srv_format + ',\n' + table_data += ' ' + rtv_format + ',\n' + table_data += ' ' + dsv_format + ');\n' + table_data += ' return textureFormat;\n' + table_data += ' }\n' + + return table_data + +def parse_json_into_switch_string(json_data): + table_data = '' + for internal_format_item in sorted(json_data.iteritems()): + internal_format = internal_format_item[0] + table_data += ' case ' + internal_format + ':\n' + table_data += ' {\n' + + for idx, texture_format in enumerate(sorted(json_data[internal_format])): + table_data += get_texture_format_item(idx, texture_format) + + table_data += ' else\n' + table_data += ' {\n' + table_data += ' break;\n' + table_data += ' }\n' + table_data += ' }\n' + + return table_data + +with open('texture_format_data.json') as texture_format_json_file: + texture_format_data = texture_format_json_file.read(); + texture_format_json_file.close() + json_data = json.loads(texture_format_data) + + table_data = parse_json_into_switch_string(json_data) + output = template.format(data=table_data) + + with open('texture_format_table_autogen.cpp', 'wt') as out_file: + out_file.write(output) + out_file.close() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp new file mode 100644 index 00000000000..adb20a5e60f --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp @@ -0,0 +1,170 @@ +// +// 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/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h new file mode 100644 index 00000000000..2d538e1d82f --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h @@ -0,0 +1,31 @@ +// +// 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/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json new file mode 100644 index 00000000000..cb1d8595a23 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json @@ -0,0 +1,1107 @@ +{ + "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" + } + ] + } +}
\ No newline at end of file diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h new file mode 100644 index 00000000000..60ab41fd838 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h @@ -0,0 +1,30 @@ +// +// 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" + +namespace rx +{ + +namespace d3d11 +{ + +const std::map<GLenum, LoadImageFunction> &GetLoadFunctionsMap(GLenum internalFormat, + DXGI_FORMAT dxgiFormat); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp new file mode 100644 index 00000000000..788f792e7b2 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp @@ -0,0 +1,2079 @@ +// 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/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, LoadImageFunction> &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, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadA32FToRGBA32F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadA32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadA32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadA8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_BGR5_A1_ANGLEX: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadRGB5A1ToRGBA8; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadRGB5A1ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA4_ANGLEX: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadRGBA4ToRGBA8; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadRGBA4ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_R11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadEACR11ToR8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RG11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadEACRG11ToRG8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGB8_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGB8ToRGBA8; + 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, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGB8A1ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGBA8_ETC2_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGBA8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_SIGNED_R11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadEACR11SToR8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SIGNED_RG11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadEACRG11SToRG8; + 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, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGBA8ToSRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SRGB8_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGB8ToRGBA8; + 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, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGB8A1ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH24_STENCIL8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT_24_8] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT_24_8] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH32F_STENCIL8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadToNative<GLuint,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_DEPTH_COMPONENT16: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D16_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadR32ToR16; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH_COMPONENT24: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH_COMPONENT32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_TYPELESS: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadToNative<GLfloat,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_DEPTH_COMPONENT32_OES: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ETC1_RGB8_OES: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadETC1RGB8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_LUMINANCE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadL32FToRGBA32F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadL32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadL32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE8_ALPHA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadLA8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadLA8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadL8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadL8ToRGBA8; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadLA32FToRGBA32F; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F; + loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadLA32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadLA32FToRGBA32F; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_R11F_G11F_B10F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadRGB16FToRG11B10F; + loadMap[GL_HALF_FLOAT_OES] = LoadRGB16FToRG11B10F; + loadMap[GL_FLOAT] = LoadRGB32FToRG11B10F; + loadMap[GL_UNSIGNED_INT_10F_11F_11F_REV] = LoadToNative<GLuint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = Load32FTo16F<1>; + loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,1>; + loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_SHORT] = LoadToNative<GLshort,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadToNative<GLfloat,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_INT] = LoadToNative<GLint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = Load32FTo16F<2>; + loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,2>; + loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_SHORT] = LoadToNative<GLshort,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadToNative<GLfloat,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_INT] = LoadToNative<GLint,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,2>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_RGB10_A2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadToNative<GLuint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB10_A2UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadToNative<GLuint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadRGB32FToRGBA16F; + loadMap[GL_HALF_FLOAT] = LoadToNative3To4<GLhalf,gl::Float16One>; + loadMap[GL_HALF_FLOAT_OES] = LoadToNative3To4<GLhalf,gl::Float16One>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_SHORT] = LoadToNative3To4<GLshort,0x0001>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative3To4<GLushort,0x0001>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadToNative3To4<GLfloat,gl::Float32One>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_INT] = LoadToNative3To4<GLint,0x00000001>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadToNative3To4<GLuint,0x00000001>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB565: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadToNative<GLushort,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadR5G6B5ToRGBA8; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB5_A1: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadRGB5A1ToA1RGB5; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadRGB10A2ToRGBA8; + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadRGB5A1ToRGBA8; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative3To4<GLbyte,0x01>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0x01>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative3To4<GLbyte,0x7F>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB9_E5: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_HALF_FLOAT] = LoadRGB16FToRGB9E5; + loadMap[GL_HALF_FLOAT_OES] = LoadRGB16FToRGB9E5; + loadMap[GL_FLOAT] = LoadRGB32FToRGB9E5; + loadMap[GL_UNSIGNED_INT_5_9_9_9_REV] = LoadToNative<GLuint,1>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = UnreachableLoadFunction; + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = UnreachableLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_RGBA16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = Load32FTo16F<4>; + loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,4>; + loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_SHORT] = LoadToNative<GLshort,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_FLOAT] = LoadToNative<GLfloat,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_INT] = LoadToNative<GLint,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA4: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadRGBA4ToARGB4; + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadRGBA4ToRGBA8; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_BYTE] = LoadToNative<GLbyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_SRGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_SRGB8_ALPHA8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_STENCIL_INDEX8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = UnimplementedLoadFunction; + loadMap[DXGI_FORMAT_R24G8_TYPELESS] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() { + std::map<GLenum, LoadImageFunction> loadMap; + loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = UnimplementedLoadFunction; + loadMap[DXGI_FORMAT_R24G8_TYPELESS] = UnimplementedLoadFunction; + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + + default: + { + static std::map<GLenum, LoadImageFunction> emptyLoadFunctionsMap; + return emptyLoadFunctionsMap; + } + } + // clang-format on + +} // GetLoadFunctionsMap + +} // namespace d3d11 + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index 26b10265304..8b351e1c33f 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -1070,7 +1070,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons } // GL core feature limits - caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); + // Reserve MAX_UINT for D3D11's primitive restart. + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1); caps->max3DTextureSize = static_cast<GLuint>(GetMaximum3DTextureSize(featureLevel)); caps->max2DTextureSize = static_cast<GLuint>(GetMaximum2DTextureSize(featureLevel)); caps->maxCubeMapTextureSize = static_cast<GLuint>(GetMaximumCubeMapTextureSize(featureLevel)); @@ -1208,11 +1209,14 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); extensions->fragDepth = true; extensions->textureUsage = true; // This could be false since it has no effect in D3D11 - extensions->discardFramebuffer = false; // TODO: enable this once BUG:497445 is fixed (Chrome WebGL video tests fail with this extension active) + extensions->discardFramebuffer = true; extensions->translatedShaderSource = true; extensions->fboRenderMipmap = false; extensions->debugMarker = true; extensions->eglImage = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->vertexArrayObject = 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. @@ -1296,6 +1300,11 @@ void GenerateInitialTextureData(GLint internalFormat, const Renderer11DeviceCaps } } +UINT GetPrimitiveRestartIndex() +{ + return std::numeric_limits<UINT>::max(); +} + void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) { vertex->x = x; @@ -1325,6 +1334,56 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) #endif } +LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, + size_t inputDescLen, + const BYTE *byteCode, + size_t byteCodeLen, + const char *debugName) + : mInputDesc(inputDescLen), + mByteCodeLen(byteCodeLen), + mByteCode(byteCode), + mDebugName(debugName) +{ + memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); +} + +ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + + if (mResource == nullptr) + { + HRESULT result = + device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()), + mByteCode, mByteCodeLen, &mResource); + ASSERT(SUCCEEDED(result)); + UNUSED_ASSERTION_VARIABLE(result); + d3d11::SetDebugName(mResource, mDebugName); + } + + return mResource; +} + +LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName) + : mDesc(desc), mDebugName(debugName) +{ +} + +ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + + if (mResource == nullptr) + { + HRESULT result = device->CreateBlendState(&mDesc, &mResource); + ASSERT(SUCCEEDED(result)); + UNUSED_ASSERTION_VARIABLE(result); + d3d11::SetDebugName(mResource, mDebugName); + } + + return mResource; +} + WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) { WorkaroundsD3D workarounds; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h index 3949b644c2f..809b1af31c4 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -71,6 +71,8 @@ void GenerateInitialTextureData(GLint internalFormat, const Renderer11DeviceCaps GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, std::vector< std::vector<BYTE> > *outData); +UINT GetPrimitiveRestartIndex(); + struct PositionTexCoordVertex { float x, y; @@ -294,35 +296,17 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout> const char *mDebugName; }; -inline LazyInputLayout::LazyInputLayout( - const D3D11_INPUT_ELEMENT_DESC *inputDesc, - size_t inputDescLen, - const BYTE *byteCode, - size_t byteCodeLen, - const char *debugName) - : mInputDesc(inputDescLen), - mByteCodeLen(byteCodeLen), - mByteCode(byteCode), - mDebugName(debugName) -{ - memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); -} - -inline ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +class LazyBlendState final : public LazyResource<ID3D11BlendState> { - checkAssociatedDevice(device); + public: + LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName); - 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); - } + ID3D11BlendState *resolve(ID3D11Device *device) override; - return mResource; -} + private: + D3D11_BLEND_DESC mDesc; + const char *mDebugName; +}; // Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to // represent an entire buffer. diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json new file mode 100644 index 00000000000..3e9e6877d99 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json @@ -0,0 +1,77 @@ +{ + "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/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp deleted file mode 100644 index 39b0ad70c2e..00000000000 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp +++ /dev/null @@ -1,118 +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 -// - -#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) -{ -} - -typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair; - -const SwizzleInfoMap &BuildSwizzleInfoMap() -{ - static SwizzleInfoMap map; - - map.insert( - SwizzleInfoPair(SwizzleSizeType(8, GL_UNSIGNED_NORMALIZED), - SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), - SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R16G16B16A16_UNORM))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), - SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), - SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert( - SwizzleInfoPair(SwizzleSizeType(8, GL_SIGNED_NORMALIZED), - SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM))); - - map.insert(SwizzleInfoPair( - SwizzleSizeType(16, GL_FLOAT), - SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(32, GL_FLOAT), - SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert( - SwizzleInfoPair(SwizzleSizeType(8, GL_UNSIGNED_INT), - SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(16, GL_UNSIGNED_INT), - SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(32, GL_UNSIGNED_INT), - SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_UINT))); - - map.insert( - SwizzleInfoPair(SwizzleSizeType(8, GL_INT), - SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(16, GL_INT), - SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT))); - map.insert(SwizzleInfoPair( - SwizzleSizeType(32, GL_INT), - SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, - DXGI_FORMAT_R32G32B32A32_SINT))); - - return map; -} - -} // namespace d3d11 - -} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h index 4b1f0244950..df9a30ff505 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h @@ -42,9 +42,7 @@ struct SwizzleFormatInfo SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat); }; -typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap; - -const SwizzleInfoMap &BuildSwizzleInfoMap(); +const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType); } // namespace d3d11 diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp new file mode 100644 index 00000000000..84d6fada976 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp @@ -0,0 +1,203 @@ +// 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/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json new file mode 100644 index 00000000000..79f6f864fc2 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json @@ -0,0 +1,686 @@ +{ + "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": [ + { + "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_DEPTH32F_STENCIL8": [ + { + "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH_COMPONENT16": [ + { + "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" + }, + { + "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_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" + }, + { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL9_3" + } + ] +} diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp index aae0d8ca86d..c37a89150a8 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp @@ -340,16 +340,19 @@ const D3D11ES3FormatMap &BuildD3D11FormatMap() // Compressed formats, From ES 3.0.1 spec, table 3.16 // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | Requirements - InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus); + + // From GL_ETC1_RGB8_OES + InsertD3D11FormatInfo(&map, GL_ETC1_RGB8_OES, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, AnyDevice); // From GL_EXT_texture_compression_dxt1 InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, AnyDevice); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp new file mode 100644 index 00000000000..ecaa3fd28be --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp @@ -0,0 +1,1775 @@ +// 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. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// texture_format_table: +// Queries for full textureFormat information based in internalFormat +// + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "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" + +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) +{ + // 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; + } + } + 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; + } + } + 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)) + { + 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_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; + } + } + 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; + } + } + 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; + } + } + case GL_BGRA_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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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)) + { + 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; + } + else + { + break; + } + } + 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; + } + } + case GL_DEPTH_COMPONENT16: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + 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; + } + else + { + break; + } + } + 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)) + { + 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; + } + else + { + break; + } + } + 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; + } + } + case GL_DEPTH_COMPONENT32_OES: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + 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; + } + else + { + break; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + case GL_RGB565: + { + if (SupportsFormat<DXGI_FORMAT_B5G6R5_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_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; + } + else + { + break; + } + } + 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)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + case GL_RGBA4: + { + if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_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_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; + } + else + { + break; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + case GL_STENCIL_INDEX8: + { + 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)) + { + 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; + } + else + { + break; + } + } + + default: + break; + } + // clang-format on + + static const TextureFormat defaultInfo; + return defaultInfo; +} // GetTextureFormatInfo + +} // namespace d3d11 + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp index 17cbcc1c8c7..6479f408493 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp @@ -10,6 +10,7 @@ #include "libANGLE/renderer/d3d/d3d11/texture_format_util.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/loadimage_etc.h" namespace rx { @@ -67,6 +68,7 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap() { static D3D11LoadFunctionMap map; + // clang-format off // | Internal format | Type | Target DXGI Format | Load function | InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadToNative<GLubyte, 4> ); InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadToNative<GLubyte, 4> ); @@ -205,18 +207,20 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap() InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, LoadToNative<GLubyte, 4> ); // Compressed formats // From ES 3.0.1 spec, table 3.16 - // | Internal format | Type | Load function | - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction ); + // | Internal format | Type | Target DXGI Format | Load function + InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8_UNORM, LoadEACR11ToR8 ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8_SNORM, LoadEACR11SToR8 ); + InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8_UNORM, LoadEACRG11ToRG8 ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8_SNORM, LoadEACRG11SToRG8 ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGB8ToRGBA8 ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGB8ToRGBA8 ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGB8A1ToRGBA8 ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGB8A1ToRGBA8); + InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGBA8ToRGBA8 ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGBA8ToSRGBA8); + + // From GL_ETC1_RGB8_OES + InsertLoadFunction(&map, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC1RGB8ToRGBA8 ); // From GL_EXT_texture_compression_dxt1 InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); @@ -227,6 +231,7 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap() // From GL_ANGLE_texture_compression_dxt5 InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + // clang-format on return map; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h deleted file mode 100644 index e6c7d9923e0..00000000000 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h +++ /dev/null @@ -1,39 +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. -// -// texture_format_util: -// Contains helper functions for texture_format_table -// - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_ - -#include <map> - -#include "libANGLE/renderer/d3d/d3d11/renderer11.h" - -namespace rx -{ - -namespace d3d11 -{ - -typedef std::pair<DXGI_FORMAT, LoadImageFunction> DxgiFormatLoadFunctionPair; -typedef std::pair<GLenum, DxgiFormatLoadFunctionPair> GLTypeDXGIFunctionPair; -typedef std::map<GLenum, std::vector<GLTypeDXGIFunctionPair>> D3D11LoadFunctionMap; - -const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap(); - -typedef std::pair<GLint, DXGI_FORMAT> InitializeTextureFormatPair; -typedef std::map<InitializeTextureFormatPair, InitializeTextureDataFunction> - InternalFormatInitializerMap; - -const InternalFormatInitializerMap &BuildInternalFormatInitializerMap(); - -} // namespace d3d11 - -} // namespace rx - -#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp index 2b8b48caedd..bb66dc2faa6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp @@ -11,14 +11,31 @@ #include "common/debug.h" +#include <initguid.h> +#include <dcomp.h> + namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *) - : mWindow(window) +NativeWindow::NativeWindow(EGLNativeWindowType window, + const egl::Config *config, + bool directComposition) + : mWindow(window), + mDirectComposition(directComposition), + mDevice(nullptr), + mCompositionTarget(nullptr), + mVisual(nullptr), + mConfig(config) { } +NativeWindow::~NativeWindow() +{ + SafeRelease(mCompositionTarget); + SafeRelease(mDevice); + SafeRelease(mVisual); +} + bool NativeWindow::initialize() { return true; @@ -48,6 +65,83 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory return E_INVALIDARG; } + if (mDirectComposition) + { + HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll")); + if (!dcomp) + { + return E_INVALIDARG; + } + + typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)( + IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); + PFN_DCOMPOSITION_CREATE_DEVICE createDComp = + reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>( + GetProcAddress(dcomp, "DCompositionCreateDevice")); + if (!createDComp) + { + return E_INVALIDARG; + } + + if (!mDevice) + { + IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device); + HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice), + reinterpret_cast<void **>(&mDevice)); + SafeRelease(dxgiDevice); + + if (FAILED(result)) + { + return result; + } + } + + if (!mCompositionTarget) + { + HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget); + if (FAILED(result)) + { + return result; + } + } + + if (!mVisual) + { + HRESULT result = mDevice->CreateVisual(&mVisual); + if (FAILED(result)) + { + return result; + } + } + + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory); + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + 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; + swapChainDesc.Flags = 0; + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = + factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + *swapChain = static_cast<DXGISwapChain *>(swapChain1); + } + mVisual->SetContent(swapChain1); + mCompositionTarget->SetRoot(mVisual); + SafeRelease(factory2); + return result; + } + // 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) @@ -59,7 +153,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + 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; @@ -84,7 +179,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory 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_BACK_BUFFER; + 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; @@ -94,4 +190,12 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory return factory->CreateSwapChain(device, &swapChainDesc, swapChain); } + +void NativeWindow::commitChange() +{ + if (mDevice) + { + mDevice->Commit(); + } +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp index 5eb1d8c4409..47a6daed2d0 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -11,12 +11,22 @@ namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *config) +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 diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp index 69d3cf5e0d9..804b6971ced 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -38,7 +38,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) memcpy(mMemory.data(), data, size); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); updateD3DBufferUsage(usage); return gl::Error(GL_NO_ERROR); @@ -66,7 +66,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) memcpy(mMemory.data() + offset, data, size); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } @@ -79,7 +79,7 @@ gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintp memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp index e4dfd41cec0..c8d5d8bb075 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -53,7 +53,7 @@ gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangl return gl::Error(GL_NO_ERROR); } -gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams) +gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams) { const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0); const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment(); @@ -64,16 +64,22 @@ gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &cle return error; } - float nearZ = state.getNearPlane(); - float farZ = state.getFarPlane(); - mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true); + 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); - mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled()); + mRenderer->setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); } -gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const { ASSERT(pack.pixelBuffer.get() == nullptr); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h index 223259de0f2..fe12079ae0b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -26,10 +26,14 @@ class Framebuffer9 : public FramebufferD3D gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; private: - gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; - - gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const override; + gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp index a64f6ca4e01..df0fae41937 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -480,6 +480,8 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa 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 d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); ASSERT(d3dFormatInfo.loadFunction != NULL); @@ -498,8 +500,9 @@ 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), inputRowPitch, 0, - reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); + reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, + inputRowPitch, 0, reinterpret_cast<uint8_t *>(locked.pBits), + locked.Pitch, 0); unlock(); @@ -513,7 +516,8 @@ gl::Error Image9::loadCompressedData(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); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index fad3e29b2cf..47187816b98 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -8,49 +8,49 @@ #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include <sstream> +#include <EGL/eglext.h> + #include "common/utilities.h" +#include "libANGLE/angletypes.h" #include "libANGLE/Buffer.h" #include "libANGLE/Display.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Program.h" #include "libANGLE/Renderbuffer.h" -#include "libANGLE/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/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/d3d9/Blit9.h" #include "libANGLE/renderer/d3d/d3d9/Buffer9.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/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/d3d9/renderer9_utils.h" -#include "libANGLE/renderer/d3d/d3d9/formatutils9.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 "third_party/trace_event/trace_event.h" -#include <sstream> -#include <EGL/eglext.h> -#include <EGL/eglext.h> #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 @@ -76,8 +76,7 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display) - : RendererD3D(display) +Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this) { mD3d9Module = NULL; @@ -132,6 +131,8 @@ Renderer9::Renderer9(egl::Display *display) mAppliedProgramSerial = 0; initializeDebugAnnotator(); + + mEGLDevice = nullptr; } Renderer9::~Renderer9() @@ -154,6 +155,7 @@ void Renderer9::release() releaseDeviceResources(); + SafeDelete(mEGLDevice); SafeRelease(mDevice); SafeRelease(mDeviceEx); SafeRelease(mD3d9); @@ -527,6 +529,8 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) outExtensions->imageBase = true; outExtensions->glTexture2DImage = true; outExtensions->glRenderbufferImage = true; + + outExtensions->flexibleSurfaceCompatibility = true; } void Renderer9::startScene() @@ -648,9 +652,14 @@ gl::Error Renderer9::finish() return gl::Error(GL_NO_ERROR); } -SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) { - return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); + return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, + orientation); } void *Renderer9::getD3DDevice() @@ -883,349 +892,77 @@ gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/, return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +void Renderer9::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) { - bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; - - if (rasterStateChanged) - { - // Set the cull mode - if (rasterState.cullFace) - { - mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } - - if (rasterState.polygonOffsetFill) - { - if (mCurDepthSize > 0) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); - - float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; - - return gl::Error(GL_NO_ERROR); + mStateManager.syncState(state, bitmask); } -gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) +gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode) { - bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0; - bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; - - if (blendStateChanged || blendColorChanged) - { - if (blendState.blend) - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); - } - else - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha))); - } - - mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); - - if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || - blendState.destBlendRGB != blendState.destBlendAlpha || - blendState.blendEquationRGB != blendState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - } - } - else - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - } - - if (blendState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); - GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; - - // Set the color mask - bool zeroColorMaskAllowed = 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::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, - formatInfo.greenBits > 0 && blendState.colorMaskGreen, - formatInfo.blueBits > 0 && blendState.colorMaskBlue, - formatInfo.alphaBits > 0 && blendState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + // 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); - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - - mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - } - - if (sampleMaskChanged) + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) { - // Set the multisample mask - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); - - mCurSampleMask = sampleMask; + return error; } - mForceSetBlendState = false; + // Setting viewport state + setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), + data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace, + false); - return gl::Error(GL_NO_ERROR); -} + // Setting scissors state + setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); -gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - bool depthStencilStateChanged = mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; - bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || - stencilBackRef != mCurStencilBackRef; - bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; + // Setting blend, depth stencil, and rasterizer states + int samples = framebufferObject->getSamples(data); + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); - if (depthStencilStateChanged) - { - if (depthStencilState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } + unsigned int mask = GetBlendSampleMask(data, samples); + error = setBlendDepthRasterStates(data, mask); - mCurDepthStencilState = depthStencilState; - } - - if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) + if (error.isError()) { - if (depthStencilState.stencilTest && mCurStencilSize > 0) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - // get the maximum size of the stencil ref - unsigned int maxStencil = (1 << mCurStencilSize) - 1; - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilWritemask); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilMask); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilBackWritemask); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilBackMask); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); - - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurFrontFaceCCW = frontFaceCCW; + return error; } - mForceSetDepthStencilState = false; + mStateManager.resetDirtyBits(); - return gl::Error(GL_NO_ERROR); + return error; } void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) { - bool scissorChanged = mForceSetScissor || - memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled; - - if (scissorChanged) - { - if (enabled) - { - RECT rect; - rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width)); - rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height)); - rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width)); - rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height)); - mDevice->SetScissorRect(&rect); - } - - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); + mStateManager.setScissorState(scissor, enabled); +} - mScissorEnabled = enabled; - mCurScissor = scissor; - } +gl::Error Renderer9::setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode) +{ + int samples = glData.state->getDrawFramebuffer()->getSamples(glData); + gl::RasterizerState rasterizer = glData.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); - mForceSetScissor = false; + unsigned int mask = GetBlendSampleMask(glData, samples); + return mStateManager.setBlendDepthRasterStates(*glData.state, mask); } -void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, +void Renderer9::setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, bool ignoreViewport) { - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = static_cast<int>(mRenderTargetDesc.width); - actualViewport.height = static_cast<int>(mRenderTargetDesc.height); - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - D3DVIEWPORT9 dxViewport; - dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width)); - dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y)); - dxViewport.MinZ = actualZNear; - dxViewport.MaxZ = actualZFar; - - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; - if (viewportChanged) - { - mDevice->SetViewport(&dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - mCurDepthFront = depthFront; - - dx_VertexConstants vc = {}; - dx_PixelConstants pc = {}; - - vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; - vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; - vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; - vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; - - pc.viewCoords[0] = actualViewport.width * 0.5f; - pc.viewCoords[1] = actualViewport.height * 0.5f; - pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = depthFront; - - vc.depthRange[0] = actualZNear; - vc.depthRange[1] = actualZFar; - vc.depthRange[2] = actualZFar - actualZNear; - - pc.depthRange[0] = actualZNear; - pc.depthRange[1] = actualZFar; - pc.depthRange[2] = actualZFar - actualZNear; - - if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mVertexConstants = vc; - mDxUniformsDirty = true; - } - - if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mPixelConstants = pc; - mDxUniformsDirty = true; - } - } - - mForceSetViewport = false; + mStateManager.setViewportState(caps, viewport, zNear, zFar, drawMode, frontFace, + ignoreViewport); } bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) @@ -1273,15 +1010,14 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu { ASSERT(depthbuffer); - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); + const gl::Extents &size = depthbuffer->getSize(); // search cached nullcolorbuffers for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { if (mNullColorbufferCache[i].buffer != NULL && - mNullColorbufferCache[i].width == width && - mNullColorbufferCache[i].height == height) + mNullColorbufferCache[i].width == size.width && + mNullColorbufferCache[i].height == size.height) { mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; *outColorBuffer = mNullColorbufferCache[i].buffer; @@ -1290,7 +1026,7 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu } gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); - gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height); + gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height); if (error.isError()) { SafeDelete(nullRenderbuffer); @@ -1312,8 +1048,8 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu delete oldest->buffer; oldest->buffer = nullbuffer; oldest->lruCount = ++mMaxNullColorbufferLRU; - oldest->width = width; - oldest->height = height; + oldest->width = size.width; + oldest->height = size.height; *outColorBuffer = nullbuffer; return gl::Error(GL_NO_ERROR); @@ -1405,17 +1141,8 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt mDevice->SetDepthStencilSurface(NULL); } - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) - { - mCurStencilSize = stencilSize; - mForceSetDepthStencilState = true; - } + mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize); + mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize); mAppliedDepthStencilSerial = depthStencilSerial; mDepthStencilInitialized = true; @@ -1423,13 +1150,9 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt if (renderTargetChanged || !mRenderTargetDescInitialized) { - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight); mRenderTargetDescInitialized = true; } @@ -1453,9 +1176,18 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLin } // Applies the indices and element array bindings to the Direct3D 9 device -gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) +gl::Error Renderer9::applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo, + SourceIndexData *sourceIndexInfo) { - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo); + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, + indexInfo, sourceIndexInfo, false); if (error.isError()) { return error; @@ -1483,8 +1215,7 @@ void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) gl::Error Renderer9::drawArraysImpl(const gl::Data &data, GLenum mode, GLsizei count, - GLsizei instances, - bool usesPointSize) + GLsizei instances) { ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); @@ -1525,19 +1256,21 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data, } } -gl::Error Renderer9::drawElementsImpl(GLenum mode, +gl::Error Renderer9::drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, - const TranslatedIndexData &indexInfo, - GLsizei /*instances*/, - bool /*usesPointSize*/) + GLsizei /*instances*/) { startScene(); int minIndex = static_cast<int>(indexInfo.indexRange.start); + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + if (mode == GL_POINTS) { return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); @@ -1860,15 +1593,9 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyShaders(gl::Program *program, - const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, - bool transformFeedbackActive) +gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/) { - ASSERT(!transformFeedbackActive); - ASSERT(!rasterizerDiscard); - - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); const auto &inputLayout = programD3D->getCachedInputLayout(); ShaderExecutableD3D *vertexExe = NULL; @@ -1878,8 +1605,9 @@ gl::Error Renderer9::applyShaders(gl::Program *program, return error; } + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); if (error.isError()) { return error; @@ -1909,7 +1637,7 @@ gl::Error Renderer9::applyShaders(gl::Program *program, if (programSerial != mAppliedProgramSerial) { programD3D->dirtyAllUniforms(); - mDxUniformsDirty = true; + mStateManager.forceSetDXUniformsState(); mAppliedProgramSerial = programSerial; } @@ -1917,6 +1645,7 @@ gl::Error Renderer9::applyShaders(gl::Program *program, } gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, + GLenum /*drawMode*/, const std::vector<D3DUniform *> &uniformArray) { for (const D3DUniform *targetUniform : uniformArray) @@ -1959,12 +1688,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, } // Driver uniforms - if (mDxUniformsDirty) - { - mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); - mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); - mDxUniformsDirty = false; - } + mStateManager.setShaderConstants(); return gl::Error(GL_NO_ERROR); } @@ -2198,14 +1922,17 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetStreamSourceFreq(i, 1); } + int renderTargetWidth = mStateManager.getRenderTargetWidth(); + int renderTargetHeight = mStateManager.getRenderTargetHeight(); + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.height - 0.5f; + quad[0][1] = renderTargetHeight - 0.5f; quad[0][2] = 0.0f; quad[0][3] = 1.0f; - quad[1][0] = mRenderTargetDesc.width - 0.5f; - quad[1][1] = mRenderTargetDesc.height - 0.5f; + quad[1][0] = renderTargetWidth - 0.5f; + quad[1][1] = renderTargetHeight - 0.5f; quad[1][2] = 0.0f; quad[1][3] = 1.0f; @@ -2214,7 +1941,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, quad[2][2] = 0.0f; quad[2][3] = 1.0f; - quad[3][0] = mRenderTargetDesc.width - 0.5f; + quad[3][0] = renderTargetWidth - 0.5f; quad[3][1] = -0.5f; quad[3][2] = 0.0f; quad[3][3] = 1.0f; @@ -2263,11 +1990,11 @@ void Renderer9::markAllStateDirty() mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; - mForceSetDepthStencilState = true; - mForceSetRasterState = true; - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; + mStateManager.forceSetRasterState(); + mStateManager.forceSetDepthStencilState(); + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.forceSetViewportState(); ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size()); for (unsigned int i = 0; i < mCurVertexTextures.size(); i++) @@ -2287,7 +2014,7 @@ void Renderer9::markAllStateDirty() mAppliedVertexShader = NULL; mAppliedPixelShader = NULL; mAppliedProgramSerial = 0; - mDxUniformsDirty = true; + mStateManager.forceSetDXUniformsState(); mVertexDeclarationCache.markStateDirty(); } @@ -2723,12 +2450,15 @@ ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data) return new ProgramD3D(data, this); } -gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +gl::Error Renderer9::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) { // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); + ASSERT(streamOutVaryings.empty()); switch (type) { @@ -2762,13 +2492,16 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, +gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) { // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); + ASSERT(streamOutVaryings.empty()); const char *profileType = NULL; switch (type) @@ -2831,7 +2564,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string } error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + streamOutVaryings, separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -3042,6 +2775,26 @@ gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStar return gl::Error(GL_NO_ERROR); } +egl::Error Renderer9::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) + { + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice), + EGL_D3D9_DEVICE_ANGLE, EGL_FALSE); + + if (error.isError()) + { + SafeDelete(mEGLDevice); + return error; + } + } + + *device = static_cast<DeviceImpl *>(mEGLDevice); + return egl::Error(EGL_SUCCESS); +} + Renderer9::CurSamplerState::CurSamplerState() : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h index e7d8a3f1af9..4e3fb9cea86 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -17,6 +17,7 @@ #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" namespace gl { @@ -78,7 +79,11 @@ class Renderer9 : public RendererD3D gl::Error flush() override; gl::Error finish() override; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); void freeEventQuery(IDirect3DQuery9* query); @@ -96,28 +101,32 @@ class Renderer9 : public RendererD3D const std::vector<GLint> &vertexUniformBuffers, const std::vector<GLint> &fragmentUniformBuffers) override; - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); + gl::Error updateState(const gl::Data &data, GLenum drawMode) override; - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + void setViewport(const gl::Caps *caps, + 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, const gl::FramebufferAttachment *depthStencilAttachment); - gl::Error applyShaders(gl::Program *program, - const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, - bool transformFeedbackActive) override; 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, SourceIndexData *sourceInfo); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo); + gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo, + SourceIndexData *sourceIndexInfo) override; void applyTransformFeedbackBuffers(const gl::State &state) override; @@ -131,7 +140,7 @@ class Renderer9 : public RendererD3D bool testDeviceLost() override; bool testDeviceResettable() override; - VendorID getVendorId() const override; + VendorID getVendorId() const; std::string getRendererDescription() const override; DeviceIdentifier getAdapterIdentifier() const override; @@ -173,14 +182,20 @@ class Renderer9 : public RendererD3D ProgramImpl *createProgram(const gl::Program::Data &data) override; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, - ShaderExecutableD3D **outExectuable); - virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector<D3DVarying> &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations virtual ImageD3D *createImage(); @@ -221,6 +236,8 @@ class Renderer9 : public RendererD3D 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; + // D3D9-renderer specific methods gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); @@ -236,24 +253,25 @@ class Renderer9 : public RendererD3D 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; private: gl::Error drawArraysImpl(const gl::Data &data, GLenum mode, GLsizei count, - GLsizei instances, - bool usesPointSize) override; - gl::Error drawElementsImpl(GLenum mode, + GLsizei instances) override; + gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, - const TranslatedIndexData &indexInfo, - GLsizei instances, - bool usesPointSize) override; + GLsizei instances) override; void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions, @@ -261,6 +279,8 @@ class Renderer9 : public RendererD3D WorkaroundsD3D generateWorkarounds() const override; + gl::Error setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode); + void release(); void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v); @@ -315,43 +335,10 @@ class Renderer9 : public RendererD3D unsigned int mAppliedDepthStencilSerial; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - unsigned int mCurStencilSize; - unsigned int mCurDepthSize; - - struct RenderTargetDesc - { - size_t width; - size_t height; - D3DFORMAT format; - }; - RenderTargetDesc mRenderTargetDesc; IDirect3DStateBlock9 *mMaskedClearSavedState; - // previously set render states - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - bool mCurFrontFaceCCW; - - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - bool mForceSetScissor; - gl::Rectangle mCurScissor; - bool mScissorEnabled; - - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - float mCurDepthFront; - - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - GLuint mCurSampleMask; + StateManager9 mStateManager; // Currently applied sampler states struct CurSamplerState @@ -374,10 +361,6 @@ class Renderer9 : public RendererD3D IDirect3DPixelShader9 *mAppliedPixelShader; unsigned int mAppliedProgramSerial; - dx_VertexConstants mVertexConstants; - dx_PixelConstants mPixelConstants; - bool mDxUniformsDirty; - // A pool of event queries that are currently unused. std::vector<IDirect3DQuery9*> mEventQueryPool; VertexShaderCache mVertexShaderCache; @@ -399,6 +382,8 @@ class Renderer9 : public RendererD3D gl::FramebufferAttachment *buffer; } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; UINT mMaxNullColorbufferLRU; + + DeviceD3D *mEGLDevice; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp new file mode 100644 index 00000000000..1ae98f7d266 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp @@ -0,0 +1,898 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager9.cpp: Defines a class for caching D3D9 state +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +StateManager9::StateManager9(Renderer9 *renderer9) + : mCurBlendState(), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mCurRasterState(), + mCurDepthSize(0), + mCurDepthStencilState(), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurFrontFaceCCW(0), + mCurStencilSize(0), + mCurScissorRect(), + mCurScissorEnabled(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mCurDepthFront(0.0f), + mCurIgnoreViewport(false), + mRenderer9(renderer9), + mDirtyBits() +{ + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK); + mBlendStateDirtyBits.set(DIRTY_BIT_DITHER); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK); + + mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE); + mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); +} + +StateManager9::~StateManager9() +{ +} + +void StateManager9::forceSetBlendState() +{ + mDirtyBits |= mBlendStateDirtyBits; +} + +void StateManager9::forceSetRasterState() +{ + mDirtyBits |= mRasterizerStateDirtyBits; +} + +void StateManager9::forceSetDepthStencilState() +{ + mDirtyBits |= mDepthStencilStateDirtyBits; +} + +void StateManager9::forceSetScissorState() +{ + mDirtyBits |= mScissorStateDirtyBits; +} + +void StateManager9::forceSetViewportState() +{ + mForceSetViewport = true; +} + +void StateManager9::forceSetDXUniformsState() +{ + mDxUniformsDirty = true; +} + +void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + forceSetDepthStencilState(); + } +} + +void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + // BlendColor and funcs and equations has to be set if blend is enabled + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + } + break; + case gl::State::DIRTY_BIT_BLEND_FUNCS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || + blendState.destBlendRGB != mCurBlendState.destBlendRGB || + blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || + blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + // BlendColor depends on the values of blend funcs + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + } + break; + } + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || + blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + } + break; + } + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + } + break; + case gl::State::DIRTY_BIT_COLOR_MASK: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || + blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || + blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || + blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + } + break; + } + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mDirtyBits.set(DIRTY_BIT_DITHER); + } + break; + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + + // Viewport state depends on rasterizer.frontface + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterizerState = state.getRasterizerState(); + if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + } + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + // If we enable the stencil test, all of these must be set + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc || + depthStencilState.stencilMask != mCurDepthStencilState.stencilMask || + state.getStencilRef() != mCurStencilRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || + depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask || + state.getStencilBackRef() != mCurStencilBackRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail || + depthStencilState.stencilPassDepthFail != + mCurDepthStencilState.stencilPassDepthFail || + depthStencilState.stencilPassDepthPass != + mCurDepthStencilState.stencilPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail || + depthStencilState.stencilBackPassDepthFail != + mCurDepthStencilState.stencilBackPassDepthFail || + depthStencilState.stencilBackPassDepthPass != + mCurDepthStencilState.stencilBackPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + // If scissor is enabled, we have to set the scissor rect + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + default: + break; + } + } +} + +gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, + unsigned int sampleMask) +{ + const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + + const gl::BlendState &blendState = glState.getBlendState(); + const gl::ColorF &blendColor = glState.getBlendColor(); + const gl::RasterizerState &rasterState = glState.getRasterizerState(); + + const auto &depthStencilState = glState.getDepthStencilState(); + bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW); + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + // All the depth stencil states depends on the front face ccw variable + if (frontFaceCCW != mCurFrontFaceCCW) + { + forceSetDepthStencilState(); + mCurFrontFaceCCW = frontFaceCCW; + } + + for (auto dirtyBit : angle::IterateBitSet(mDirtyBits)) + { + switch (dirtyBit) + { + case DIRTY_BIT_BLEND_ENABLED: + setBlendEnabled(blendState.blend); + break; + case DIRTY_BIT_BLEND_COLOR: + setBlendColor(blendState, blendColor); + break; + case DIRTY_BIT_BLEND_FUNCS_EQUATIONS: + setBlendFuncsEquations(blendState); + break; + case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE: + setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage); + break; + case DIRTY_BIT_COLOR_MASK: + setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue, + blendState.colorMaskGreen, blendState.colorMaskAlpha); + break; + case DIRTY_BIT_DITHER: + setDither(blendState.dither); + break; + case DIRTY_BIT_CULL_MODE: + setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace); + break; + case DIRTY_BIT_DEPTH_BIAS: + setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor, + rasterState.polygonOffsetUnits); + break; + case DIRTY_BIT_STENCIL_DEPTH_MASK: + setDepthMask(depthStencilState.depthMask); + break; + case DIRTY_BIT_STENCIL_DEPTH_FUNC: + setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc); + break; + case DIRTY_BIT_STENCIL_TEST_ENABLED: + setStencilTestEnabled(depthStencilState.stencilTest); + break; + case DIRTY_BIT_STENCIL_FUNCS_FRONT: + setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask, + glState.getStencilRef(), frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_FUNCS_BACK: + setStencilFuncsBack(depthStencilState.stencilBackFunc, + depthStencilState.stencilBackMask, glState.getStencilBackRef(), + frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_BACK: + setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_FRONT: + setStencilOpsFront(depthStencilState.stencilFail, + depthStencilState.stencilPassDepthFail, + depthStencilState.stencilPassDepthPass, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_BACK: + setStencilOpsBack(depthStencilState.stencilBackFail, + depthStencilState.stencilBackPassDepthFail, + depthStencilState.stencilBackPassDepthPass, frontFaceCCW); + break; + default: + break; + } + } + + if (sampleMask != mCurSampleMask) + { + setSampleMask(sampleMask); + } + + return gl::Error(GL_NO_ERROR); +} + +void StateManager9::setViewportState(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport) +{ + if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport) + return; + + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = static_cast<int>(mRenderTargetBounds.width); + actualViewport.height = static_cast<int>(mRenderTargetBounds.height); + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height)); + dxViewport.Width = + gl::clamp(actualViewport.width, 0, + static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X)); + dxViewport.Height = + gl::clamp(actualViewport.height, 0, + static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + mRenderer9->getDevice()->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + mCurIgnoreViewport = ignoreViewport; + + // Setting shader constants + dx_VertexConstants vc = {}; + dx_PixelConstants pc = {}; + + vc.viewAdjust[0] = + static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) + + 2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) / + dxViewport.Width; + vc.viewAdjust[1] = + static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) + + 2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) / + dxViewport.Height; + vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width; + vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + + mForceSetViewport = false; +} + +void StateManager9::setShaderConstants() +{ + if (!mDxUniformsDirty) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants), + sizeof(dx_VertexConstants) / sizeof(float[4])); + device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants), + sizeof(dx_PixelConstants) / sizeof(float[4])); + mDxUniformsDirty = false; +} + +// This is separate from the main state loop because other functions +// outside call only setScissorState to update scissor state +void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled) +{ + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED)) + setScissorEnabled(enabled); + + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT)) + setScissorRect(scissor, enabled); +} + +void StateManager9::setRenderTargetBounds(size_t width, size_t height) +{ + mRenderTargetBounds.width = (int)width; + mRenderTargetBounds.height = (int)height; + forceSetViewportState(); +} + +void StateManager9::setScissorEnabled(bool scissorEnabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE); + mCurScissorEnabled = scissorEnabled; +} + +void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled) +{ + if (!enabled) + return; + + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height)); + rect.right = + gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width)); + rect.bottom = + gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height)); + mRenderer9->getDevice()->SetScissorRect(&rect); +} + +void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc) +{ + if (depthTest) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState.depthTest = depthTest; + mCurDepthStencilState.depthFunc = depthFunc; +} + +void StateManager9::setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW) +{ + // TODO(dianx) It may be slightly more efficient todo these and other similar areas + // with separate dirty bits. + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilPassDepthFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilPassDepthPass)); + + mCurDepthStencilState.stencilFail = stencilFail; + mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail; + mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass; +} + +void StateManager9::setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilBackFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass)); + + mCurDepthStencilState.stencilBackFail = stencilBackFail; + mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail; + mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask); + + mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask; +} + +void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilBackFunc)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + stencilBackMask); + + mCurDepthStencilState.stencilBackFunc = stencilBackFunc; + mCurStencilBackRef = stencilBackRef; + mCurDepthStencilState.stencilBackMask = stencilBackMask; +} + +void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask); + mCurDepthStencilState.stencilWritemask = stencilWriteMask; +} + +void StateManager9::setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilFunc)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask); + + mCurDepthStencilState.stencilFunc = stencilFunc; + mCurStencilRef = stencilRef; + mCurDepthStencilState.stencilMask = stencilMask; +} +void StateManager9::setStencilTestEnabled(bool stencilTestEnabled) +{ + if (stencilTestEnabled && mCurStencilSize > 0) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mCurDepthStencilState.stencilTest = stencilTestEnabled; +} + +void StateManager9::setDepthMask(bool depthMask) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE); + mCurDepthStencilState.depthMask = depthMask; +} + +// TODO(dianx) one bit for sampleAlphaToCoverage +void StateManager9::setSampleAlphaToCoverage(bool enabled) +{ + if (enabled) + { + FIXME("Sample alpha to coverage is unimplemented."); + } +} + +void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor) +{ + if (!blendState.blend) + return; + + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && + blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR, + gl_d3d9::ConvertColor(blendColor)); + } + else + { + mRenderer9->getDevice()->SetRenderState( + D3DRS_BLENDFACTOR, + D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha))); + } + mCurBlendColor = blendColor; +} + +void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState) +{ + if (!blendState.blend) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + + device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + device->SetRenderState(D3DRS_DESTBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + device->SetRenderState(D3DRS_BLENDOPALPHA, + gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + + mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB; + mCurBlendState.destBlendRGB = blendState.destBlendRGB; + mCurBlendState.blendEquationRGB = blendState.blendEquationRGB; + mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha; +} + +void StateManager9::setBlendEnabled(bool enabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE); + mCurBlendState.blend = enabled; +} + +void StateManager9::setDither(bool dither) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE); + mCurBlendState.dither = dither; +} + +// TODO(dianx) one bit for color mask +void StateManager9::setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha) +{ + // Set the color mask + 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); + + 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) + { + 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); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + + mCurBlendState.colorMaskRed = red; + mCurBlendState.colorMaskGreen = green; + mCurBlendState.colorMaskBlue = blue; + mCurBlendState.colorMaskAlpha = alpha; +} + +void StateManager9::setSampleMask(unsigned int sampleMask) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + // Set the multisample mask + device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); + + mCurSampleMask = sampleMask; +} + +void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace) +{ + if (cullFace) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, + gl_d3d9::ConvertCullMode(cullMode, frontFace)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + mCurRasterState.cullFace = cullFace; + mCurRasterState.cullMode = cullMode; + mCurRasterState.frontFace = frontFace; +} + +void StateManager9::setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits) +{ + if (polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor); + + float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); + device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias); + } + } + else + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + device->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState.polygonOffsetFill = polygonOffsetFill; + mCurRasterState.polygonOffsetFactor = polygonOffsetFactor; + mCurRasterState.polygonOffsetUnits = polygonOffsetUnits; +} + +void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize) +{ + if (!depthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + forceSetRasterState(); + } +} +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h new file mode 100644 index 00000000000..630685587cb --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h @@ -0,0 +1,192 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager9.h: Defines a class for caching D3D9 state + +#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ +#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Data.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +class Renderer9; + +class StateManager9 final : angle::NonCopyable +{ + public: + StateManager9(Renderer9 *renderer9); + ~StateManager9(); + + 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, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport); + + void setShaderConstants(); + + void forceSetBlendState(); + void forceSetRasterState(); + void forceSetDepthStencilState(); + void forceSetScissorState(); + void forceSetViewportState(); + void forceSetDXUniformsState(); + + void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize); + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + void setRenderTargetBounds(size_t width, size_t height); + + int getRenderTargetWidth() const { return mRenderTargetBounds.width; } + int getRenderTargetHeight() const { return mRenderTargetBounds.height; } + + void resetDirtyBits() { mDirtyBits.reset(); } + + private: + // Blend state functions + void setBlendEnabled(bool enabled); + void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor); + void setBlendFuncsEquations(const gl::BlendState &blendState); + void setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha); + void setSampleAlphaToCoverage(bool enabled); + void setDither(bool dither); + void setSampleMask(unsigned int sampleMask); + + // Current raster state functions + void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace); + void setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits); + + // Depth stencil state functions + void setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW); + void setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW); + void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW); + void setDepthFunc(bool depthTest, GLenum depthFunc); + void setStencilTestEnabled(bool enabled); + void setDepthMask(bool depthMask); + void setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW); + + void setScissorEnabled(bool scissorEnabled); + void setScissorRect(const gl::Rectangle &scissor, bool enabled); + + enum DirtyBitType + { + // Blend dirty bits + DIRTY_BIT_BLEND_ENABLED, + DIRTY_BIT_BLEND_COLOR, + DIRTY_BIT_BLEND_FUNCS_EQUATIONS, + DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE, + DIRTY_BIT_COLOR_MASK, + DIRTY_BIT_DITHER, + DIRTY_BIT_SAMPLE_MASK, + + // Rasterizer dirty bits + DIRTY_BIT_CULL_MODE, + DIRTY_BIT_DEPTH_BIAS, + + // Depth stencil dirty bits + DIRTY_BIT_STENCIL_DEPTH_MASK, + DIRTY_BIT_STENCIL_DEPTH_FUNC, + DIRTY_BIT_STENCIL_TEST_ENABLED, + DIRTY_BIT_STENCIL_FUNCS_FRONT, + DIRTY_BIT_STENCIL_FUNCS_BACK, + DIRTY_BIT_STENCIL_WRITEMASK_FRONT, + DIRTY_BIT_STENCIL_WRITEMASK_BACK, + DIRTY_BIT_STENCIL_OPS_FRONT, + DIRTY_BIT_STENCIL_OPS_BACK, + + // Scissor dirty bits + DIRTY_BIT_SCISSOR_ENABLED, + DIRTY_BIT_SCISSOR_RECT, + + // Viewport dirty bits + DIRTY_BIT_VIEWPORT, + + DIRTY_BIT_MAX + }; + + typedef std::bitset<DIRTY_BIT_MAX> DirtyBits; + + // Currently applied blend state + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + DirtyBits mBlendStateDirtyBits; + + // Currently applied raster state + gl::RasterizerState mCurRasterState; + unsigned int mCurDepthSize; + DirtyBits mRasterizerStateDirtyBits; + + // Currently applied depth stencil state + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + unsigned int mCurStencilSize; + DirtyBits mDepthStencilStateDirtyBits; + + // Currently applied scissor states + gl::Rectangle mCurScissorRect; + bool mCurScissorEnabled; + gl::Extents mRenderTargetBounds; + DirtyBits mScissorStateDirtyBits; + + // Currently applied viewport states + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + bool mCurIgnoreViewport; + + dx_VertexConstants mVertexConstants; + dx_PixelConstants mPixelConstants; + bool mDxUniformsDirty; + + // FIXME: Unsupported by D3D9 + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + + Renderer9 *mRenderer9; + DirtyBits mDirtyBits; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp index 5ce76f8ae9b..be6a9c424ca 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -15,21 +15,26 @@ namespace rx { -SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChain9::SwapChain9(Renderer9 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mSwapInterval(-1), + mSwapChain(nullptr), + mBackBuffer(nullptr), + mRenderTarget(nullptr), + mDepthStencil(nullptr), + mOffscreenTexture(nullptr), mColorRenderTarget(this, false), mDepthStencilRenderTarget(this, true) { - mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = -1; + ASSERT(orientation == 0); } SwapChain9::~SwapChain9() diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h index 9c67f7165b2..55a700c2d64 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -20,8 +20,12 @@ class Renderer9; class SwapChain9 : public SwapChainD3D { public: - SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChain9(Renderer9 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); virtual ~SwapChain9(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); @@ -45,8 +49,8 @@ class SwapChain9 : public SwapChainD3D void release(); Renderer9 *mRenderer; - EGLint mHeight; EGLint mWidth; + EGLint mHeight; EGLint mSwapInterval; IDirect3DSwapChain9 *mSwapChain; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp index afa01811024..b931035ef62 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -574,6 +574,9 @@ void GenerateCaps(IDirect3D9 *d3d9, extensions->colorBufferFloat = false; extensions->debugMarker = true; extensions->eglImage = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->vertexArrayObject = true; // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil // state. diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp new file mode 100644 index 00000000000..97eb9929951 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp @@ -0,0 +1,953 @@ +// +// 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 +{ + +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); + } + } + + 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 + { + // Table 3.17.2 sorted according to table 3.17.3 + // clang-format off + static const int intensityModifierDefault[8][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[8][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 + + const int(&intensityModifier)[8][4] = + nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; + + R8G8B8A8 subblockColors0[4]; + R8G8B8A8 subblockColors1[4]; + for (size_t blockIdx = 0; blockIdx < 4; blockIdx++) + { + const int i1 = intensityModifier[u.idht.mode.idm.cw1][blockIdx]; + subblockColors0[blockIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1); + + const int i2 = intensityModifier[u.idht.mode.idm.cw2][blockIdx]; + subblockColors1[blockIdx] = 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; + } + } + + // 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 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 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/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h new file mode 100644 index 00000000000..2ada743a243 --- /dev/null +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h @@ -0,0 +1,130 @@ +// +// 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 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_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp index b6aa401fc53..0a624dcb17d 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp @@ -58,10 +58,14 @@ BlitGL::BlitGL(const FunctionsGL *functions, mWorkarounds(workarounds), mStateManager(stateManager), mBlitProgram(0), - mScratchTexture(0), mScratchFBO(0), mVAO(0) { + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) + { + mScratchTextures[i] = 0; + } + ASSERT(mFunctions); ASSERT(mStateManager); } @@ -70,25 +74,28 @@ BlitGL::~BlitGL() { if (mBlitProgram != 0) { - mFunctions->deleteProgram(mBlitProgram); + mStateManager->deleteProgram(mBlitProgram); mBlitProgram = 0; } - if (mScratchTexture != 0) + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) { - mFunctions->deleteTextures(1, &mScratchTexture); - mScratchTexture = 0; + if (mScratchTextures[i] != 0) + { + mStateManager->deleteTexture(mScratchTextures[i]); + mScratchTextures[i] = 0; + } } if (mScratchFBO != 0) { - mFunctions->deleteFramebuffers(1, &mScratchFBO); + mStateManager->deleteFramebuffer(mScratchFBO); mScratchFBO = 0; } if (mVAO != 0) { - mFunctions->deleteVertexArrays(1, &mVAO); + mStateManager->deleteVertexArray(mVAO); mVAO = 0; } } @@ -129,16 +136,18 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture, return error; } - // Blit the framebuffer to the scratch texture + // Blit the framebuffer to the first scratch texture const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat( mFunctions, mWorkarounds, source->getImplementationColorReadFormat(), source->getImplementationColorReadType()); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat); mStateManager->activeTexture(0); - mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height, 0); @@ -150,15 +159,20 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture, }; mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); - // Make a temporary framebuffer using the destination texture + // Make a temporary framebuffer using the second scratch texture to render the swizzled result + // to. + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[1]); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width, + sourceArea.height, 0, internalFormatInfo.format, + source->getImplementationColorReadType(), nullptr); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO); - mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture, - static_cast<GLint>(level)); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mScratchTextures[1], 0); // Render to the destination texture, sampling from the scratch texture mStateManager->useProgram(mBlitProgram); - mStateManager->setViewport( - gl::Rectangle(destOffset.x, destOffset.y, sourceArea.width, sourceArea.height)); + mStateManager->setViewport(gl::Rectangle(0, 0, sourceArea.width, sourceArea.height)); mStateManager->setScissorTestEnabled(false); mStateManager->setDepthRange(0.0f, 1.0f); mStateManager->setBlendEnabled(false); @@ -170,11 +184,17 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture, mStateManager->setCullFaceEnabled(false); mStateManager->setPolygonOffsetFillEnabled(false); mStateManager->setRasterizerDiscardEnabled(false); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); mStateManager->bindVertexArray(mVAO, 0); mFunctions->drawArrays(GL_TRIANGLES, 0, 6); + // Finally, copy the swizzled texture to the destination texture + mStateManager->bindTexture(textureType, texture); + mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y, 0, + 0, sourceArea.width, sourceArea.height); + return gl::Error(GL_NO_ERROR); } @@ -256,14 +276,17 @@ gl::Error BlitGL::initializeResources() mFunctions->uniform1i(textureUniform, 0); } - if (mScratchTexture == 0) + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) { - mFunctions->genTextures(1, &mScratchTexture); - mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture); + if (mScratchTextures[i] == 0) + { + mFunctions->genTextures(1, &mScratchTextures[i]); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[i]); - // Use nearest, non-mipmapped sampling with the scratch texture - mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Use nearest, non-mipmapped sampling with the scratch texture + mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } } if (mScratchFBO == 0) diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h index 6d7d34f9256..3ab8319bb13 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h @@ -61,7 +61,7 @@ class BlitGL : public angle::NonCopyable GLuint mBlitProgram; - GLuint mScratchTexture; + GLuint mScratchTextures[2]; GLuint mScratchFBO; GLuint mVAO; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp index 8c809d6ce8b..16cbc3c7345 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp @@ -62,8 +62,10 @@ egl::Error DisplayGL::createContext(const egl::Config *config, const gl::Context EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT); bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); + bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE); - *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess); + *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, + robustAccess, debug); return egl::Error(EGL_SUCCESS); } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp index 92e08cc06f3..1f4f4e03fcd 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp @@ -19,6 +19,7 @@ #include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/TextureGL.h" #include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "platform/Platform.h" namespace rx { @@ -212,7 +213,10 @@ gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask) return gl::Error(GL_NO_ERROR); } -gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +gl::Error FramebufferGL::clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) { syncClearBufferState(buffer, drawbuffer); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); @@ -221,7 +225,10 @@ gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GL return gl::Error(GL_NO_ERROR); } -gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +gl::Error FramebufferGL::clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) { syncClearBufferState(buffer, drawbuffer); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); @@ -230,7 +237,10 @@ gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, G return gl::Error(GL_NO_ERROR); } -gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +gl::Error FramebufferGL::clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) { syncClearBufferState(buffer, drawbuffer); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); @@ -239,7 +249,11 @@ gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GL return gl::Error(GL_NO_ERROR); } -gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +gl::Error FramebufferGL::clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) { syncClearBufferState(buffer, drawbuffer); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); @@ -285,17 +299,21 @@ gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourc mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID); - mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height, - destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height, - mask, filter); + mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(), + destArea.x, destArea.y, destArea.x1(), destArea.y1(), mask, filter); return gl::Error(GL_NO_ERROR); } -GLenum FramebufferGL::checkStatus() const +bool FramebufferGL::checkStatus() const { mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); - return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER); + GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + { + ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete."); + } + return (status == GL_FRAMEBUFFER_COMPLETE); } GLuint FramebufferGL::getFramebufferID() const diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h index edc4fa7fafe..f8d006ac697 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h @@ -49,10 +49,23 @@ class FramebufferGL : public FramebufferImpl gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + gl::Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) override; + gl::Error clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) override; + gl::Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) override; GLenum getImplementationColorReadFormat() const override; GLenum getImplementationColorReadType() const override; @@ -61,7 +74,7 @@ class FramebufferGL : public FramebufferImpl gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; - GLenum checkStatus() const override; + bool checkStatus() const override; void syncDrawState() const; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp index d3b6f824635..37e13a4d3b1 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp @@ -788,14 +788,11 @@ void FunctionsGL::initialize() } // Check the context profile + profile = 0; if (isAtLeastGL(gl::Version(3, 2))) { getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); } - else - { - profile = 0; - } // clang-format off @@ -908,6 +905,39 @@ void FunctionsGL::initialize() AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv); AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv); + // GL_ARB_occlusion_query + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGenQueriesARB"), &genQueries); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glDeleteQueriesARB"), &deleteQueries); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glIsQueryARB"), &isQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glBeginQueryARB"), &beginQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glEndQueryARB"), &endQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryivARB"), &getQueryiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv); + + // EXT_transform_feedback + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferRangeEXT"), &bindBufferRange); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferBaseEXT"), &bindBufferBase); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBeginTransformFeedbackEXT"), &beginTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glEndTransformFeedbackEXT"), &endTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glTransformFeedbackVaryingsEXT"), &transformFeedbackVaryings); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glGetTransformFeedbackVaryingEXT"), &getTransformFeedbackVarying); + + // GL_ARB_transform_feedback2 + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glIsTransformFeedback"), &isTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback); + + // GL_ARB_transform_feedback3 + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glEndQueryIndexed"), &endQueryIndexed); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv); + // 1.0 if (isAtLeastGL(gl::Version(1, 0))) { diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp index b05d7f5b509..f5adc3b29bd 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp @@ -13,6 +13,7 @@ #include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/ShaderGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h" +#include "platform/Platform.h" namespace rx { @@ -46,11 +47,39 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream) return gl::Error(GL_INVALID_OPERATION); } +void ProgramGL::setBinaryRetrievableHint(bool retrievable) +{ + UNIMPLEMENTED(); +} + LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) { // Reset the program state, delete the current program if one exists reset(); + // Set the transform feedback state + std::vector<const GLchar *> transformFeedbackVaryings; + for (const auto &tfVarying : mData.getTransformFeedbackVaryingNames()) + { + transformFeedbackVaryings.push_back(tfVarying.c_str()); + } + + if (transformFeedbackVaryings.empty()) + { + if (mFunctions->transformFeedbackVaryings) + { + mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, + mData.getTransformFeedbackBufferMode()); + } + } + else + { + ASSERT(mFunctions->transformFeedbackVaryings); + mFunctions->transformFeedbackVaryings( + mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()), + &transformFeedbackVaryings[0], mData.getTransformFeedbackBufferMode()); + } + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); @@ -82,7 +111,6 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) // Verify the link GLint linkStatus = GL_FALSE; mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus); - ASSERT(linkStatus == GL_TRUE); if (linkStatus == GL_FALSE) { // Linking failed, put the error into the info log @@ -95,8 +123,11 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) mFunctions->deleteProgram(mProgramID); mProgramID = 0; - infoLog << &buf[0]; - TRACE("\n%s", &buf[0]); + infoLog << buf.data(); + + std::string warning = FormatString("Program link failed unexpectedly: %s", buf.data()); + ANGLEPlatformCurrent()->logWarning(warning.c_str()); + TRACE("\n%s", warning.c_str()); // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case return LinkResult(false, gl::Error(GL_NO_ERROR)); @@ -289,13 +320,29 @@ void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean t void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - mFunctions->uniformBlockBinding(mProgramID, mUniformBlockRealLocationMap[uniformBlockIndex], - uniformBlockBinding); + // Lazy init + if (mUniformBlockRealLocationMap.empty()) + { + mUniformBlockRealLocationMap.reserve(mData.getUniformBlocks().size()); + for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks()) + { + const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex(); + GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str()); + mUniformBlockRealLocationMap.push_back(blockIndex); + } + } + + GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex]; + if (realBlockIndex != GL_INVALID_INDEX) + { + mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding); + } } void ProgramGL::reset() { mUniformRealLocationMap.clear(); + mUniformBlockRealLocationMap.clear(); mSamplerBindings.clear(); mUniformIndexToSamplerIndex.clear(); } @@ -310,105 +357,50 @@ const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() cons return mSamplerBindings; } -void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks, - std::vector<gl::LinkedUniform> *uniforms) +bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const { - mUniformBlockRealLocationMap.resize(uniformBlocks->size(), 0); + ASSERT(mProgramID != 0u); - for (int i = 0; i < static_cast<int>(uniformBlocks->size()); i++) + GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str()); + if (blockIndex == GL_INVALID_INDEX) { - auto &uniformBlock = uniformBlocks->at(i); - - std::stringstream fullNameStr; - fullNameStr << uniformBlock.name; - if (uniformBlock.isArray) - { - fullNameStr << "[" << uniformBlock.arrayElement << "]"; - } - - GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, fullNameStr.str().c_str()); - if (blockIndex != GL_INVALID_INDEX) - { - mUniformBlockRealLocationMap[i] = blockIndex; - - GLint dataSize = 0; - mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, - &dataSize); - uniformBlock.dataSize = dataSize; - } - else - { - // Remove this uniform block - uniformBlocks->erase(uniformBlocks->begin() + i); - i--; - } + *sizeOut = 0; + return false; } - for (int uniformIdx = 0; uniformIdx < static_cast<int>(uniforms->size()); uniformIdx++) - { - auto &uniform = uniforms->at(uniformIdx); - if (uniform.isInDefaultBlock()) - { - continue; - } + GLint dataSize = 0; + mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, + &dataSize); + *sizeOut = static_cast<size_t>(dataSize); + return true; +} - const GLchar *uniformName = uniform.name.c_str(); - GLuint uniformIndex = 0; - mFunctions->getUniformIndices(mProgramID, 1, &uniformName, &uniformIndex); +bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const +{ + GLuint uniformIndex; + const GLchar *memberNameGLStr = memberUniformName.c_str(); + mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex); - if (uniformIndex == GL_INVALID_INDEX) - { - // Uniform member has been optimized out, remove it from the list - // TODO: Clean this up by using a class to wrap around the uniforms so manual removal is - // not needed. - for (size_t uniformBlockIdx = 0; uniformBlockIdx < uniformBlocks->size(); - uniformBlockIdx++) - { - auto &uniformBlock = uniformBlocks->at(uniformBlockIdx); - for (int memberIndex = 0; - memberIndex < static_cast<int>(uniformBlock.memberUniformIndexes.size()); - memberIndex++) - { - if (uniformBlock.memberUniformIndexes[memberIndex] == - static_cast<unsigned int>(uniformIdx)) - { - uniformBlock.memberUniformIndexes.erase( - uniformBlock.memberUniformIndexes.begin() + memberIndex); - memberIndex--; - } - else if (uniformBlock.memberUniformIndexes[memberIndex] > - static_cast<unsigned int>(uniformIdx)) - { - uniformBlock.memberUniformIndexes[memberIndex]--; - } - } - } - uniforms->erase(uniforms->begin() + uniformIdx); - uniformIdx--; - } - else - { - GLint offset = 0; - mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET, - &offset); - uniform.blockInfo.offset = offset; - - GLint arrayStride = 0; - mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE, - &arrayStride); - uniform.blockInfo.arrayStride = arrayStride; - - GLint matrixStride = 0; - mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE, - &matrixStride); - uniform.blockInfo.matrixStride = matrixStride; - - // TODO: determine this at the gl::Program level. - GLint isRowMajorMatrix = 0; - mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR, - &isRowMajorMatrix); - uniform.blockInfo.isRowMajorMatrix = isRowMajorMatrix != GL_FALSE; - } + if (uniformIndex == GL_INVALID_INDEX) + { + *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; } + + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET, + &memberInfoOut->offset); + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE, + &memberInfoOut->arrayStride); + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE, + &memberInfoOut->matrixStride); + + // TODO(jmadill): possibly determine this at the gl::Program level. + GLint isRowMajorMatrix = 0; + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR, + &isRowMajorMatrix); + memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE; + return true; } -} + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h index 35c755ed6f1..fa343688a61 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h @@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; gl::Error save(gl::BinaryOutputStream *stream) override; + void setBinaryRetrievableHint(bool retrievable) override; LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; @@ -61,8 +62,9 @@ class ProgramGL : public ProgramImpl void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; - void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks, - std::vector<gl::LinkedUniform> *uniforms) override; + bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; + bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const override; GLuint getProgramID() const; const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp index 8f1d25f3bbd..a8c9a9b9885 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp @@ -9,39 +9,160 @@ #include "libANGLE/renderer/gl/QueryGL.h" #include "common/debug.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +namespace +{ + +GLuint MergeQueryResults(GLenum type, GLuint currentResult, GLuint newResult) +{ + switch (type) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return currentResult + newResult; + + default: + UNREACHABLE(); + return 0; + } +} + +} // anonymous namespace namespace rx { -QueryGL::QueryGL(GLenum type) - : QueryImpl(type) -{} +QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager) + : QueryImpl(type), + mType(type), + mFunctions(functions), + mStateManager(stateManager), + mActiveQuery(0), + mPendingQueries(), + mResultSum(0) +{ +} QueryGL::~QueryGL() -{} +{ + mStateManager->deleteQuery(mActiveQuery); + mStateManager->onDeleteQueryObject(this); + while (!mPendingQueries.empty()) + { + mStateManager->deleteQuery(mPendingQueries.front()); + mPendingQueries.pop_front(); + } +} gl::Error QueryGL::begin() { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); + mResultSum = 0; + return gl::Error(GL_NO_ERROR); } gl::Error QueryGL::end() { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); + return pause(); } gl::Error QueryGL::getResult(GLuint *params) { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); + ASSERT(mActiveQuery == 0); + + gl::Error error = flush(true); + if (error.isError()) + { + return error; + } + + ASSERT(mPendingQueries.empty()); + *params = mResultSum; + + return gl::Error(GL_NO_ERROR); } gl::Error QueryGL::isResultAvailable(GLuint *available) { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); + ASSERT(mActiveQuery == 0); + + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + *available = mPendingQueries.empty() ? GL_TRUE : GL_FALSE; + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::pause() +{ + if (mActiveQuery != 0) + { + mStateManager->endQuery(mType, mActiveQuery); + + mPendingQueries.push_back(mActiveQuery); + mActiveQuery = 0; + } + + // Flush to make sure the pending queries don't add up too much. + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::resume() +{ + if (mActiveQuery == 0) + { + // Flush to make sure the pending queries don't add up too much. + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + mFunctions->genQueries(1, &mActiveQuery); + mStateManager->beginQuery(mType, mActiveQuery); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::flush(bool force) +{ + while (!mPendingQueries.empty()) + { + GLuint id = mPendingQueries.front(); + if (!force) + { + GLuint resultAvailable = 0; + mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable); + if (resultAvailable == GL_FALSE) + { + return gl::Error(GL_NO_ERROR); + } + } + + GLuint result = 0; + mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result); + mResultSum = MergeQueryResults(mType, mResultSum, result); + + mStateManager->deleteQuery(id); + + mPendingQueries.pop_front(); + } + + return gl::Error(GL_NO_ERROR); } } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h index c6b7cfbfef4..7385ff9dcfc 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h @@ -9,21 +9,47 @@ #ifndef LIBANGLE_RENDERER_GL_QUERYGL_H_ #define LIBANGLE_RENDERER_GL_QUERYGL_H_ +#include <deque> + #include "libANGLE/renderer/QueryImpl.h" namespace rx { +class FunctionsGL; +class StateManagerGL; + class QueryGL : public QueryImpl { public: - QueryGL(GLenum type); + QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager); ~QueryGL() override; gl::Error begin() override; gl::Error end() override; gl::Error getResult(GLuint *params) override; gl::Error isResultAvailable(GLuint *available) override; + + // OpenGL is only allowed to have one query of each type active at any given time. Since ANGLE + // virtualizes contexts, queries need to be able to be paused and resumed. + // A query is "paused" by ending it and pushing the ID into a list of queries awaiting readback. + // When it is "resumed", a new query is generated and started. + // When a result is required, the queries are "flushed" by iterating over the list of pending + // queries and merging their results. + gl::Error pause(); + gl::Error resume(); + + private: + gl::Error flush(bool force); + + GLenum mType; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mActiveQuery; + std::deque<GLuint> mPendingQueries; + GLuint mResultSum; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp index 6a8ab11a3d5..0661b8d3bf6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp @@ -86,6 +86,7 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at mFunctions(functions), mStateManager(nullptr), mBlitter(nullptr), + mHasDebugOutput(false), mSkipDrawCalls(false) { ASSERT(mFunctions); @@ -93,8 +94,12 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds); mBlitter = new BlitGL(functions, mWorkarounds, mStateManager); + mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) || + mFunctions->hasGLExtension("GL_KHR_debug") || + mFunctions->isAtLeastGLES(gl::Version(3, 2)) || + mFunctions->hasGLESExtension("GL_KHR_debug"); #ifndef NDEBUG - if (mFunctions->debugMessageControl && mFunctions->debugMessageCallback) + if (mHasDebugOutput) { mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE); @@ -114,8 +119,8 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at RendererGL::~RendererGL() { - SafeDelete(mStateManager); SafeDelete(mBlitter); + SafeDelete(mStateManager); } gl::Error RendererGL::flush() @@ -126,7 +131,22 @@ gl::Error RendererGL::flush() gl::Error RendererGL::finish() { +#ifdef NDEBUG + if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput) + { + mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#endif + mFunctions->finish(); + +#ifdef NDEBUG + if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput) + { + mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#endif + return gl::Error(GL_NO_ERROR); } @@ -280,7 +300,7 @@ VertexArrayImpl *RendererGL::createVertexArray(const gl::VertexArray::Data &data QueryImpl *RendererGL::createQuery(GLenum type) { - return new QueryGL(type); + return new QueryGL(type, mFunctions, mStateManager); } FenceNVImpl *RendererGL::createFenceNV() @@ -295,7 +315,8 @@ FenceSyncImpl *RendererGL::createFenceSync() TransformFeedbackImpl *RendererGL::createTransformFeedback() { - return new TransformFeedbackGL(); + return new TransformFeedbackGL(mFunctions, mStateManager, + getRendererCaps().maxTransformFeedbackSeparateComponents); } SamplerImpl *RendererGL::createSampler() @@ -342,12 +363,6 @@ bool RendererGL::testDeviceResettable() return bool(); } -VendorID RendererGL::getVendorId() const -{ - UNIMPLEMENTED(); - return VendorID(); -} - std::string RendererGL::getVendorString() const { return std::string(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR))); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h index e52502dc873..4d51bb5ac6e 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h @@ -99,7 +99,6 @@ class RendererGL : public Renderer bool testDeviceLost() override; bool testDeviceResettable() override; - VendorID getVendorId() const override; std::string getVendorString() const override; std::string getRendererDescription() const override; @@ -124,6 +123,8 @@ class RendererGL : public Renderer WorkaroundsGL mWorkarounds; + bool mHasDebugOutput; + // For performance debugging bool mSkipDrawCalls; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp index 52efd449fd6..4a6e2f14dd6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp @@ -36,7 +36,8 @@ ShaderGL::~ShaderGL() } } -int ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream) +int ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string * /*sourcePath*/) { // Reset the previous state if (mShaderID != 0) @@ -70,7 +71,6 @@ bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog // Check for compile errors from the native driver GLint compileStatus = GL_FALSE; mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus); - ASSERT(compileStatus == GL_TRUE); if (compileStatus == GL_FALSE) { // Compilation failed, put the error into the info log diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h index c3e0982e87c..76139ace8f3 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h @@ -25,7 +25,8 @@ class ShaderGL : public ShaderImpl ~ShaderGL() override; // ShaderImpl implementation - int prepareSourceAndReturnOptions(std::stringstream *sourceStream) override; + int prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) override; bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; std::string getDebugInfo() const override; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp index 33dc97cf0ee..037f5d57254 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp @@ -11,18 +11,25 @@ #include "common/BitSetIterator.h" #include "libANGLE/Data.h" #include "libANGLE/Framebuffer.h" +#include "libANGLE/TransformFeedback.h" #include "libANGLE/VertexArray.h" +#include "libANGLE/Query.h" #include "libANGLE/renderer/gl/BufferGL.h" #include "libANGLE/renderer/gl/FramebufferGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/ProgramGL.h" #include "libANGLE/renderer/gl/SamplerGL.h" #include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/TransformFeedbackGL.h" #include "libANGLE/renderer/gl/VertexArrayGL.h" +#include "libANGLE/renderer/gl/QueryGL.h" namespace rx { +static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN}; + StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) { } @@ -37,6 +44,11 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren mTextureUnitIndex(0), mTextures(), mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0), + mTransformFeedback(0), + mQueries(), + mPrevDrawTransformFeedback(nullptr), + mPrevDrawQueries(), + mPrevDrawContext(0), mUnpackAlignment(4), mUnpackRowLength(0), mUnpackSkipRows(0), @@ -111,6 +123,11 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks); + for (GLenum queryType : QueryTypes) + { + mQueries[queryType] = 0; + } + // Initialize point sprite state for desktop GL if (mFunctions->standard == STANDARD_GL_DESKTOP) { @@ -246,6 +263,41 @@ void StateManagerGL::deleteRenderbuffer(GLuint rbo) } } +void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback) +{ + if (transformFeedback != 0) + { + if (mTransformFeedback == transformFeedback) + { + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); + } + + if (mPrevDrawTransformFeedback != nullptr && + mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback) + { + mPrevDrawTransformFeedback = nullptr; + } + + mFunctions->deleteTransformFeedbacks(1, &transformFeedback); + } +} + +void StateManagerGL::deleteQuery(GLuint query) +{ + if (query != 0) + { + for (auto &activeQuery : mQueries) + { + GLuint activeQueryID = activeQuery.second; + if (activeQueryID == query) + { + GLenum type = activeQuery.first; + endQuery(type, query); + } + } + } +} + void StateManagerGL::useProgram(GLuint program) { if (mProgram != program) @@ -487,6 +539,49 @@ void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer) } } +void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback) +{ + ASSERT(type == GL_TRANSFORM_FEEDBACK); + if (mTransformFeedback != transformFeedback) + { + // Pause the current transform feedback if one is active. + // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform + // feedback at any time, even if there is one active. + if (mPrevDrawTransformFeedback != nullptr && + mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback) + { + mPrevDrawTransformFeedback->syncPausedState(true); + mPrevDrawTransformFeedback = nullptr; + } + + mTransformFeedback = transformFeedback; + mFunctions->bindTransformFeedback(type, mTransformFeedback); + } +} + +void StateManagerGL::beginQuery(GLenum type, GLuint query) +{ + // Make sure this is a valid query type and there is no current active query of this type + ASSERT(mQueries.find(type) != mQueries.end()); + ASSERT(mQueries[type] == 0); + ASSERT(query != 0); + + mQueries[type] = query; + mFunctions->beginQuery(type, query); +} + +void StateManagerGL::endQuery(GLenum type, GLuint query) +{ + ASSERT(mQueries[type] == query); + mQueries[type] = 0; + mFunctions->endQuery(type); +} + +void StateManagerGL::onDeleteQueryObject(QueryGL *query) +{ + mPrevDrawQueries.erase(query); +} + gl::Error StateManagerGL::setDrawArraysState(const gl::Data &data, GLint first, GLsizei count, @@ -542,12 +637,30 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) { const gl::State &state = *data.state; + // If the context has changed, pause the previous context's transform feedback and queries + if (data.context != mPrevDrawContext) + { + if (mPrevDrawTransformFeedback != nullptr) + { + mPrevDrawTransformFeedback->syncPausedState(true); + } + + for (QueryGL *prevQuery : mPrevDrawQueries) + { + prevQuery->pause(); + } + } + mPrevDrawTransformFeedback = nullptr; + mPrevDrawQueries.clear(); + + mPrevDrawContext = data.context; + + // Sync the current program state const gl::Program *program = state.getProgram(); const ProgramGL *programGL = GetImplAs<ProgramGL>(program); useProgram(programGL->getProgramID()); - for (size_t uniformBlockIndex = 0; - uniformBlockIndex < gl::IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; + for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) { GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex)); @@ -620,6 +733,37 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) // Seamless cubemaps are required for ES3 and higher contexts. setTextureCubemapSeamlessEnabled(data.clientVersion >= 3); + // Set the current transform feedback state + gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); + if (transformFeedback) + { + TransformFeedbackGL *transformFeedbackGL = + GetImplAs<TransformFeedbackGL>(transformFeedback); + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID()); + transformFeedbackGL->syncActiveState(transformFeedback->isActive(), + transformFeedback->getPrimitiveMode()); + transformFeedbackGL->syncPausedState(transformFeedback->isPaused()); + mPrevDrawTransformFeedback = transformFeedbackGL; + } + else + { + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); + mPrevDrawTransformFeedback = nullptr; + } + + // Set the current query state + for (GLenum queryType : QueryTypes) + { + gl::Query *query = state.getActiveQuery(queryType); + if (query != nullptr) + { + QueryGL *queryGL = GetImplAs<QueryGL>(query); + queryGL->resume(); + + mPrevDrawQueries.insert(queryGL); + } + } + return gl::Error(GL_NO_ERROR); } @@ -1133,7 +1277,7 @@ void StateManagerGL::setClearStencil(GLint clearStencil) void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) { // TODO(jmadill): Investigate only syncing vertex state for active attributes - for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) + for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) { switch (dirtyBit) { @@ -1277,6 +1421,22 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; + case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; case gl::State::DIRTY_BIT_PACK_ALIGNMENT: // TODO(jmadill): split this setPixelPackState(state.getPackState()); @@ -1285,6 +1445,18 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; + case gl::State::DIRTY_BIT_PACK_ROW_LENGTH: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_SKIP_ROWS: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; case gl::State::DIRTY_BIT_DITHER_ENABLED: // TODO(jmadill): implement this break; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h index 2697acc872c..b430208ae20 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h @@ -28,6 +28,8 @@ namespace rx { class FunctionsGL; +class TransformFeedbackGL; +class QueryGL; class StateManagerGL final : angle::NonCopyable { @@ -41,6 +43,8 @@ class StateManagerGL final : angle::NonCopyable void deleteBuffer(GLuint buffer); void deleteFramebuffer(GLuint fbo); void deleteRenderbuffer(GLuint rbo); + void deleteTransformFeedback(GLuint transformFeedback); + void deleteQuery(GLuint query); void useProgram(GLuint program); void bindVertexArray(GLuint vao, GLuint elementArrayBuffer); @@ -52,6 +56,9 @@ class StateManagerGL final : angle::NonCopyable void bindSampler(size_t unit, GLuint sampler); void bindFramebuffer(GLenum type, GLuint framebuffer); void bindRenderbuffer(GLenum type, GLuint renderbuffer); + void bindTransformFeedback(GLenum type, GLuint transformFeedback); + void beginQuery(GLenum type, GLuint query); + void endQuery(GLenum type, GLuint query); void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data); @@ -115,6 +122,8 @@ class StateManagerGL final : angle::NonCopyable void setFramebufferSRGBEnabled(bool enabled); + void onDeleteQueryObject(QueryGL *query); + gl::Error setDrawArraysState(const gl::Data &data, GLint first, GLsizei count, @@ -156,6 +165,14 @@ class StateManagerGL final : angle::NonCopyable std::map<GLenum, std::vector<GLuint>> mTextures; std::vector<GLuint> mSamplers; + GLuint mTransformFeedback; + + std::map<GLenum, GLuint> mQueries; + + TransformFeedbackGL *mPrevDrawTransformFeedback; + std::set<QueryGL *> mPrevDrawQueries; + uintptr_t mPrevDrawContext; + GLint mUnpackAlignment; GLint mUnpackRowLength; GLint mUnpackSkipRows; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp index 62754448c19..c325bb199a9 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp @@ -9,51 +9,134 @@ #include "libANGLE/renderer/gl/TransformFeedbackGL.h" #include "common/debug.h" +#include "libANGLE/Data.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" namespace rx { -TransformFeedbackGL::TransformFeedbackGL() - : TransformFeedbackImpl() -{} +TransformFeedbackGL::TransformFeedbackGL(const FunctionsGL *functions, + StateManagerGL *stateManager, + size_t maxTransformFeedbackBufferBindings) + : TransformFeedbackImpl(), + mFunctions(functions), + mStateManager(stateManager), + mTransformFeedbackID(0), + mIsActive(false), + mIsPaused(false), + mCurrentIndexedBuffers(maxTransformFeedbackBufferBindings) +{ + mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID); +} TransformFeedbackGL::~TransformFeedbackGL() -{} +{ + mStateManager->deleteTransformFeedback(mTransformFeedbackID); + mTransformFeedbackID = 0; + + for (auto &bufferBinding : mCurrentIndexedBuffers) + { + bufferBinding.set(nullptr); + } +} void TransformFeedbackGL::begin(GLenum primitiveMode) { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); + // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback. } void TransformFeedbackGL::end() { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); + syncActiveState(false, GL_NONE); } void TransformFeedbackGL::pause() { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); + syncPausedState(true); } void TransformFeedbackGL::resume() { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); + // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback. } void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); } void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) { - // Skipped to prevent assertions in tests - // UNIMPLEMENTED(); + // Directly bind buffer (not through the StateManager methods) because the buffer bindings are + // tracked per transform feedback object + if (binding != mCurrentIndexedBuffers[index]) + { + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (binding.get() != nullptr) + { + const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get()); + if (binding.getSize() != 0) + { + mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, + static_cast<GLuint>(index), bufferGL->getBufferID(), + binding.getOffset(), binding.getSize()); + } + else + { + mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), + bufferGL->getBufferID()); + } + } + else + { + mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0); + } + + mCurrentIndexedBuffers[index] = binding; + } +} + +GLuint TransformFeedbackGL::getTransformFeedbackID() const +{ + return mTransformFeedbackID; +} + +void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const +{ + if (mIsActive != active) + { + mIsActive = active; + mIsPaused = false; + + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (mIsActive) + { + mFunctions->beginTransformFeedback(primitiveMode); + } + else + { + mFunctions->endTransformFeedback(); + } + } +} + +void TransformFeedbackGL::syncPausedState(bool paused) const +{ + if (mIsActive && mIsPaused != paused) + { + mIsPaused = paused; + + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (mIsPaused) + { + mFunctions->pauseTransformFeedback(); + } + else + { + mFunctions->resumeTransformFeedback(); + } + } } } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h index 9008d4e5aee..7f72077e83b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h @@ -14,10 +14,15 @@ namespace rx { +class FunctionsGL; +class StateManagerGL; + class TransformFeedbackGL : public TransformFeedbackImpl { public: - TransformFeedbackGL(); + TransformFeedbackGL(const FunctionsGL *functions, + StateManagerGL *stateManager, + size_t maxTransformFeedbackBufferBindings); ~TransformFeedbackGL() override; void begin(GLenum primitiveMode) override; @@ -27,6 +32,22 @@ class TransformFeedbackGL : public TransformFeedbackImpl void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override; void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override; + + GLuint getTransformFeedbackID() const; + + void syncActiveState(bool active, GLenum primitiveMode) const; + void syncPausedState(bool paused) const; + + private: + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mTransformFeedbackID; + + mutable bool mIsActive; + mutable bool mIsPaused; + + std::vector<OffsetBindingPointer<gl::Buffer>> mCurrentIndexedBuffers; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp index 6227a511c15..255b41f565b 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp @@ -50,7 +50,7 @@ VertexArrayGL::VertexArrayGL(const VertexArray::Data &data, mFunctions->genVertexArrays(1, &mVertexArrayID); // Set the cached vertex attribute array size - GLint maxVertexAttribs; + GLint maxVertexAttribs = 0; mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); mAppliedAttributes.resize(maxVertexAttribs); } @@ -232,7 +232,7 @@ void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &act ASSERT(mAttributesNeedStreaming.any()); const auto &attribs = mData.getVertexAttributes(); - for (unsigned int idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) + for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) { const auto &attrib = attribs[idx]; ASSERT(AttributeNeedsStreaming(attrib)); @@ -292,8 +292,7 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib size_t curBufferOffset = bufferEmptySpace; const auto &attribs = mData.getVertexAttributes(); - for (unsigned int idx : - angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) + for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) { const auto &attrib = attribs[idx]; ASSERT(AttributeNeedsStreaming(attrib)); @@ -334,13 +333,14 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib { ASSERT(!attrib.normalized); mFunctions->vertexAttribIPointer( - idx, attrib.size, attrib.type, static_cast<GLsizei>(destStride), + static_cast<GLuint>(idx), attrib.size, attrib.type, + static_cast<GLsizei>(destStride), reinterpret_cast<const GLvoid *>(vertexStartOffset)); } else { mFunctions->vertexAttribPointer( - idx, attrib.size, attrib.type, attrib.normalized, + static_cast<GLuint>(idx), attrib.size, attrib.type, attrib.normalized, static_cast<GLsizei>(destStride), reinterpret_cast<const GLvoid *>(vertexStartOffset)); } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h index 17a17795546..e05d4700482 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h @@ -18,7 +18,8 @@ struct WorkaroundsGL : avoid1BitAlphaTextureFormats(false), rgba4IsNotSupportedForColorRendering(false), doesSRGBClearsOnLinearFramebufferAttachments(false), - doWhileGLSLCausesGPUHang(false) + doWhileGLSLCausesGPUHang(false), + finishDoesNotCauseQueriesToBeAvailable(false) { } @@ -40,8 +41,8 @@ struct WorkaroundsGL // driver clears to the linearized clear color despite the framebuffer not supporting SRGB // blending. It only seems to do this when the framebuffer has only linear attachments, mixed // attachments appear to get the correct clear color. - bool doesSRGBClearsOnLinearFramebufferAttachments; + // On Mac some GLSL constructs involving do-while loops cause GPU hangs, such as the following: // int i = 1; // do { @@ -50,6 +51,11 @@ struct WorkaroundsGL // } while (i > 0) // Work around this by rewriting the do-while to use another GLSL construct (block + while) bool doWhileGLSLCausesGPUHang; + + // Calling glFinish doesn't cause all queries to report that the result is available on some + // (NVIDIA) drivers. It was found that enabling GL_DEBUG_OUTPUT_SYNCHRONOUS before the finish + // causes it to fully finish. + bool finishDoesNotCauseQueriesToBeAvailable; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm index 7e25a9bcad2..2f8ebb68fa3 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm @@ -6,15 +6,15 @@ // DisplayCGL.mm: CGL implementation of egl::Display -#include "libANGLE/renderer/gl/CGL/DisplayCGL.h" +#include "libANGLE/renderer/gl/cgl/DisplayCGL.h" #import <Cocoa/Cocoa.h> #include <dlfcn.h> #include <EGL/eglext.h> #include "common/debug.h" -#include "libANGLE/renderer/gl/CGL/PbufferSurfaceCGL.h" -#include "libANGLE/renderer/gl/CGL/WindowSurfaceCGL.h" +#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h" +#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" namespace { @@ -113,7 +113,7 @@ SurfaceImpl *DisplayCGL::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs) { - return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions); + return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions, mContext); } SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::Config *configuration, @@ -151,6 +151,10 @@ egl::ConfigSet DisplayCGL::generateConfigs() const // TODO(cwallez): generate more config permutations egl::ConfigSet configs; + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + egl::Config config; // Native stuff @@ -197,8 +201,8 @@ egl::ConfigSet DisplayCGL::generateConfigs() const config.renderTargetFormat = GL_RGBA8; config.depthStencilFormat = GL_DEPTH24_STENCIL8; - config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR; - config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR; + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.renderableType = config.conformant; config.matchNativePixmap = EGL_NONE; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h index 7bfd488ec68..80b5f58ecde 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h @@ -34,7 +34,7 @@ class PbufferSurfaceCGL : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm index b1cff47e665..ec936a60a48 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm @@ -95,7 +95,7 @@ egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void ** return egl::Error(EGL_SUCCESS); } -egl::Error PbufferSurfaceCGL::bindTexImage(EGLint buffer) +egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer) { UNIMPLEMENTED(); return egl::Error(EGL_SUCCESS); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h index a6e0a0900e4..83cbe8f092c 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h @@ -11,10 +11,14 @@ #include "libANGLE/renderer/gl/SurfaceGL.h" +struct _CGLContextObject; +typedef _CGLContextObject *CGLContextObj; @class CALayer; struct __IOSurface; typedef __IOSurface *IOSurfaceRef; +@class SwapLayer; + namespace rx { @@ -24,12 +28,36 @@ class FunctionsGL; class StateManagerGL; struct WorkaroundsGL; -class DisplayLink; +struct SharedSwapState +{ + struct SwapTexture + { + GLuint texture; + unsigned int width; + unsigned int height; + uint64_t swapId; + }; + + SwapTexture textures[3]; + + // This code path is not going to be used by Chrome so we take the liberty + // to use pthreads directly instead of using mutexes and condition variables + // via the Platform API. + pthread_mutex_t mutex; + // The following members should be accessed only when holding the mutex + // (or doing construction / destruction) + SwapTexture *beingRendered; + SwapTexture *lastRendered; + SwapTexture *beingPresented; +}; class WindowSurfaceCGL : public SurfaceGL { public: - WindowSurfaceCGL(RendererGL *renderer, CALayer *layer, const FunctionsGL *functions); + WindowSurfaceCGL(RendererGL *renderer, + CALayer *layer, + const FunctionsGL *functions, + CGLContextObj context); ~WindowSurfaceCGL() override; egl::Error initialize() override; @@ -38,7 +66,7 @@ class WindowSurfaceCGL : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; @@ -51,27 +79,16 @@ class WindowSurfaceCGL : public SurfaceGL FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; private: - struct Surface - { - IOSurfaceRef ioSurface; - GLuint texture; - uint64_t lastPresentNanos; - }; - - void freeSurfaceData(Surface *surface); - egl::Error initializeSurfaceData(Surface *surface, int width, int height); + SwapLayer *mSwapLayer; + SharedSwapState mSwapState; + uint64_t mCurrentSwapId; CALayer *mLayer; + CGLContextObj mContext; const FunctionsGL *mFunctions; StateManagerGL *mStateManager; const WorkaroundsGL &mWorkarounds; - DisplayLink *mDisplayLink; - // CGL doesn't have a default framebuffer, we instead render to an IOSurface - // that will be set as the content of the CALayer which is our native window. - // We use two IOSurfaces to do double buffering. - Surface mSurfaces[2]; - int mCurrentSurface; GLuint mFramebuffer; GLuint mDSRenderbuffer; }; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm index 04cd88e3fe5..f80bb1aa251 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm @@ -9,8 +9,6 @@ #include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" #import <Cocoa/Cocoa.h> -#include <mach/mach.h> -#include <mach/mach_time.h> #include <OpenGL/OpenGL.h> #import <QuartzCore/QuartzCore.h> @@ -20,146 +18,151 @@ #include "libANGLE/renderer/gl/RendererGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h" -#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 - -#include <iostream> - -namespace +@interface SwapLayer : CAOpenGLLayer { + CGLContextObj mDisplayContext; -// All time computations in the file are done in nanoseconds but both the -// current time and the screen's present time are given as "mach time". -// The first thing we will do after receiving a mach time is convert it. -uint64_t MachTimeToNanoseconds(uint64_t machTime) -{ - static mach_timebase_info_data_t timebaseInfo; - - if (timebaseInfo.denom == 0) - { - mach_timebase_info(&timebaseInfo); - } - - return (machTime * timebaseInfo.numer) / timebaseInfo.denom; -} - -uint64_t NowInNanoseconds() -{ - return MachTimeToNanoseconds(mach_absolute_time()); -} + bool initialized; + rx::SharedSwapState *mSwapState; + const rx::FunctionsGL *mFunctions; + GLuint mReadFramebuffer; } - -namespace rx -{ - -// A wrapper around CoreVideo's DisplayLink. It polls the screen vsync time, -// and allows computing when is the next present time after a given time point. -class DisplayLink -{ - public: - DisplayLink() : mDisplayLink(nullptr), mHostTimeRemainderNanos(0), mPresentIntervalNanos(0) {} - - ~DisplayLink() +- (id)initWithSharedState:(rx::SharedSwapState *)swapState + withContext:(CGLContextObj)displayContext + withFunctions:(const rx::FunctionsGL *)functions; +@end + +@implementation SwapLayer +- (id)initWithSharedState:(rx::SharedSwapState *)swapState + withContext:(CGLContextObj)displayContext + withFunctions:(const rx::FunctionsGL *)functions { - if (mDisplayLink != nullptr) + self = [super init]; + if (self != nil) { - stop(); - CVDisplayLinkRelease(mDisplayLink); - mDisplayLink = nullptr; + self.asynchronous = YES; + mDisplayContext = displayContext; + + initialized = false; + mSwapState = swapState; + mFunctions = functions; + + [self setFrame:CGRectMake(0, 0, mSwapState->textures[0].width, + mSwapState->textures[0].height)]; } + return self; } - void start() + - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { - CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink); - ASSERT(mDisplayLink != nullptr); - CVDisplayLinkSetOutputCallback(mDisplayLink, &Callback, this); - CVDisplayLinkStart(mDisplayLink); + CGLPixelFormatAttribute attribs[] = { + kCGLPFADisplayMask, static_cast<CGLPixelFormatAttribute>(mask), kCGLPFAOpenGLProfile, + static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core), + static_cast<CGLPixelFormatAttribute>(0)}; + + CGLPixelFormatObj pixelFormat = nullptr; + GLint numFormats = 0; + CGLChoosePixelFormat(attribs, &pixelFormat, &numFormats); + + return pixelFormat; } - void stop() + - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { - ASSERT(mDisplayLink != nullptr); - CVDisplayLinkStop(mDisplayLink); + CGLContextObj context = nullptr; + CGLCreateContext(pixelFormat, mDisplayContext, &context); + return context; } - uint64_t nextPresentAfter(uint64_t time) + - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext + pixelFormat:(CGLPixelFormatObj)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval + displayTime:(const CVTimeStamp *)timeStamp { - // Load the two variables locally to avoid them changing in the middle of the computation. - uint64_t presentInterval = mPresentIntervalNanos; - uint64_t remainder = mHostTimeRemainderNanos; + BOOL result = NO; - if (presentInterval == 0) + pthread_mutex_lock(&mSwapState->mutex); { - return time; + if (mSwapState->lastRendered->swapId > mSwapState->beingPresented->swapId) + { + std::swap(mSwapState->lastRendered, mSwapState->beingPresented); + result = YES; + } } + pthread_mutex_unlock(&mSwapState->mutex); - uint64_t nextSwapNumber = (time - remainder) / presentInterval + 1; - return nextSwapNumber * presentInterval + remainder; + return result; } - uint64_t getPresentInterval() const { return mPresentIntervalNanos; } - - private: - static CVReturn Callback(CVDisplayLinkRef displayLink, - const CVTimeStamp *now, - const CVTimeStamp *outputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *userData) + - (void)drawInCGLContext:(CGLContextObj)glContext + pixelFormat:(CGLPixelFormatObj)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval + displayTime:(const CVTimeStamp *)timeStamp { - DisplayLink *link = reinterpret_cast<DisplayLink *>(userData); - link->tick(*outputTime); - return kCVReturnSuccess; + CGLSetCurrentContext(glContext); + if (!initialized) + { + initialized = true; + + mFunctions->genFramebuffers(1, &mReadFramebuffer); + } + + const auto &texture = *mSwapState->beingPresented; + if ([self frame].size.width != texture.width || [self frame].size.height != texture.height) + { + [self setFrame:CGRectMake(0, 0, texture.width, texture.height)]; + + // Without this, the OSX compositor / window system doesn't see the resize. + [self setNeedsDisplay]; + } + + // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the + // GL_DRAW_FRAMEBUFFER_BINDING query + GLint drawFBO; + mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO); + + mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + texture.texture, 0); + + mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer); + mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width, + texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Call the super method to flush the context + [super drawInCGLContext:glContext + pixelFormat:pixelFormat + forLayerTime:timeInterval + displayTime:timeStamp]; } + @end - void tick(const CVTimeStamp &outputTime) + namespace rx { - // This is called from a special high priority thread so by setting - // both member variables here we have a data race. However if we assume - // the present interval doesn't change, the data race disappears after - // the first tick. - // In addition computations using these member variables are made to - // produce a sensible result if one of the two members has the default - // value of 0. - uint64_t hostTimeNanos = MachTimeToNanoseconds(outputTime.hostTime); - - uint64_t numerator = outputTime.videoRefreshPeriod; - uint64_t denominator = outputTime.videoTimeScale; - uint64_t presentIntervalNanos = (1000000000 * numerator) / denominator; - - mHostTimeRemainderNanos = hostTimeNanos % presentIntervalNanos; - mPresentIntervalNanos = presentIntervalNanos; - } - CVDisplayLinkRef mDisplayLink; - - uint64_t mHostTimeRemainderNanos; - uint64_t mPresentIntervalNanos; -}; - -WindowSurfaceCGL::WindowSurfaceCGL(RendererGL *renderer, - CALayer *layer, - const FunctionsGL *functions) - : SurfaceGL(renderer), - mLayer(layer), - mFunctions(functions), - mStateManager(renderer->getStateManager()), - mWorkarounds(renderer->getWorkarounds()), - mDisplayLink(nullptr), - mCurrentSurface(0), - mFramebuffer(0), - mDSRenderbuffer(0) + WindowSurfaceCGL::WindowSurfaceCGL(RendererGL *renderer, + CALayer *layer, + const FunctionsGL *functions, + CGLContextObj context) + : SurfaceGL(renderer), + mSwapLayer(nil), + mCurrentSwapId(0), + mLayer(layer), + mContext(context), + mFunctions(functions), + mStateManager(renderer->getStateManager()), + mWorkarounds(renderer->getWorkarounds()), + mFramebuffer(0), + mDSRenderbuffer(0) { - for (auto &surface : mSurfaces) - { - surface.texture = 0; - surface.ioSurface = nil; - } + pthread_mutex_init(&mSwapState.mutex, nullptr); } WindowSurfaceCGL::~WindowSurfaceCGL() { + pthread_mutex_destroy(&mSwapState.mutex); if (mFramebuffer != 0) { mFunctions->deleteFramebuffers(1, &mFramebuffer); @@ -172,14 +175,19 @@ WindowSurfaceCGL::~WindowSurfaceCGL() mDSRenderbuffer = 0; } - for (auto &surface : mSurfaces) + if (mSwapLayer != nil) { - freeSurfaceData(&surface); + [mSwapLayer release]; + mSwapLayer = nil; } - if (mDisplayLink != nullptr) + for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i) { - SafeDelete(mDisplayLink); + if (mSwapState.textures[i].texture != 0) + { + mFunctions->deleteTextures(1, &mSwapState.textures[i].texture); + mSwapState.textures[i].texture = 0; + } } } @@ -188,11 +196,24 @@ egl::Error WindowSurfaceCGL::initialize() unsigned width = getWidth(); unsigned height = getHeight(); - for (auto &surface : mSurfaces) + for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i) { - surface.lastPresentNanos = 0; - initializeSurfaceData(&surface, width, height); + mFunctions->genTextures(1, &mSwapState.textures[i].texture); + mStateManager->bindTexture(GL_TEXTURE_2D, mSwapState.textures[i].texture); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + mSwapState.textures[i].width = width; + mSwapState.textures[i].height = height; + mSwapState.textures[i].swapId = 0; } + mSwapState.beingRendered = &mSwapState.textures[0]; + mSwapState.lastRendered = &mSwapState.textures[1]; + mSwapState.beingPresented = &mSwapState.textures[2]; + + mSwapLayer = [[SwapLayer alloc] initWithSharedState:&mSwapState + withContext:mContext + withFunctions:mFunctions]; + [mLayer addSublayer:mSwapLayer]; mFunctions->genRenderbuffers(1, &mDSRenderbuffer); mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer); @@ -200,93 +221,51 @@ egl::Error WindowSurfaceCGL::initialize() mFunctions->genFramebuffers(1, &mFramebuffer); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); - mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, - mSurfaces[0].texture, 0); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSwapState.beingRendered->texture, 0); mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDSRenderbuffer); - mDisplayLink = new DisplayLink; - mDisplayLink->start(); - return egl::Error(EGL_SUCCESS); } egl::Error WindowSurfaceCGL::makeCurrent() { - // TODO(cwallez) if it is the first makeCurrent set the viewport and scissor? return egl::Error(EGL_SUCCESS); } egl::Error WindowSurfaceCGL::swap() { - // Because we are rendering to IOSurfaces we have to implement swapBuffers ourselves - // (contrary to GLX, WGL or EGL) and have to send the IOSurfaces for presentation at the - // right time to avoid causing tearing or flickering. Likewise we must make sure we do - // not render to an IOSurface that is still being presented. - // ANGLE standalone cannot post function to be executed at a later time so we can only - // implement basic synchronization with the present time by sleeping. - uint64_t presentInterval = mDisplayLink->getPresentInterval(); - uint64_t now = NowInNanoseconds(); + mFunctions->flush(); + mSwapState.beingRendered->swapId = ++mCurrentSwapId; + pthread_mutex_lock(&mSwapState.mutex); { - Surface &surface = mSurfaces[mCurrentSurface]; - // A flush is needed for the IOSurface to get the result of the GL operations - // as specified in the documentation of CGLTexImageIOSurface2D - mFunctions->flush(); - - // We can only send the IOSurface to the CALayer during a present window - // that is in the middle of two vsyncs, otherwise flickering can happen. - { - // The present window was determined empirically. - static const double kPresentWindowMin = 0.3; - static const double kPresentWindowMax = 0.7; - - uint64_t nextPresent = mDisplayLink->nextPresentAfter(now); - uint64_t presentWindowMin = nextPresent - presentInterval * (1.0 - kPresentWindowMin); - uint64_t presentWindowMax = nextPresent - presentInterval * (1.0 - kPresentWindowMax); - if (now <= presentWindowMin) - { - usleep((presentWindowMin - now) / 1000); - } - else if (now >= presentWindowMax) - { - uint64_t presentTarget = nextPresent + presentInterval * kPresentWindowMin; - usleep((presentTarget - now) / 1000); - } - } - - // Put the IOSurface as the content of the layer - [CATransaction begin]; - [mLayer setContents:(id)surface.ioSurface]; - [CATransaction commit]; - - surface.lastPresentNanos = NowInNanoseconds(); + std::swap(mSwapState.beingRendered, mSwapState.lastRendered); } + pthread_mutex_unlock(&mSwapState.mutex); - mCurrentSurface = (mCurrentSurface + 1) % ArraySize(mSurfaces); + unsigned width = getWidth(); + unsigned height = getHeight(); + auto &texture = *mSwapState.beingRendered; + if (texture.width != width || texture.height != texture.height) { - Surface &surface = mSurfaces[mCurrentSurface]; + mStateManager->bindTexture(GL_TEXTURE_2D, texture.texture); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); - { - // We need to wait a bit after a swap before rendering to the IOSurface again - // otherwise with a small desync between clocks could cause a flickering. - static const double kDrawWindowStart = 0.05; - - uint64_t timePresentFinishes = mDisplayLink->nextPresentAfter(surface.lastPresentNanos); - timePresentFinishes += presentInterval * kDrawWindowStart; + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - if (now < timePresentFinishes) - { - usleep((timePresentFinishes - now) / 1000); - } - } - - mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); - mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_RECTANGLE_ARB, surface.texture, 0); + texture.width = width; + texture.height = height; } + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSwapState.beingRendered->texture, 0); + return egl::Error(EGL_SUCCESS); } @@ -302,7 +281,7 @@ egl::Error WindowSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **v return egl::Error(EGL_SUCCESS); } -egl::Error WindowSurfaceCGL::bindTexImage(EGLint buffer) +egl::Error WindowSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer) { UNIMPLEMENTED(); return egl::Error(EGL_SUCCESS); @@ -316,7 +295,7 @@ egl::Error WindowSurfaceCGL::releaseTexImage(EGLint buffer) void WindowSurfaceCGL::setSwapInterval(EGLint interval) { - // TODO(cwallez) investigate the need for swapIntervals other than 1 + // TODO(cwallez) investigate implementing swap intervals other than 0 } EGLint WindowSurfaceCGL::getWidth() const @@ -346,53 +325,4 @@ FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Framebuffe return new FramebufferGL(mFramebuffer, data, mFunctions, mWorkarounds, mStateManager); } -void WindowSurfaceCGL::freeSurfaceData(Surface *surface) -{ - if (surface->texture != 0) - { - mFunctions->deleteTextures(1, &surface->texture); - surface->texture = 0; - } - if (surface->ioSurface != nil) - { - CFRelease(surface->ioSurface); - surface->ioSurface = nil; - } -} - -egl::Error WindowSurfaceCGL::initializeSurfaceData(Surface *surface, int width, int height) -{ - CFDictionaryRef ioSurfaceOptions = nil; - { - unsigned pixelFormat = 'BGRA'; - const unsigned kBytesPerElement = 4; - - NSDictionary *options = @{ - (id) kIOSurfaceWidth : @(width), - (id) kIOSurfaceHeight : @(height), - (id) kIOSurfacePixelFormat : @(pixelFormat), - (id) kIOSurfaceBytesPerElement : @(kBytesPerElement), - }; - ioSurfaceOptions = reinterpret_cast<CFDictionaryRef>(options); - } - - surface->ioSurface = IOSurfaceCreate(ioSurfaceOptions); - - mFunctions->genTextures(1, &surface->texture); - mFunctions->bindTexture(GL_TEXTURE_RECTANGLE_ARB, surface->texture); - - CGLError error = - CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, width, - height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface->ioSurface, 0); - - if (error != kCGLNoError) - { - std::string errorMessage = - "Could not create the IOSurfaces: " + std::string(CGLErrorString(error)); - return egl::Error(EGL_BAD_NATIVE_WINDOW, errorMessage.c_str()); - } - - return egl::Error(EGL_SUCCESS); -} - } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp index 75e24f0f4aa..b2f24f2af99 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp @@ -227,15 +227,19 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), Always(), Never(), VersionOnly(3, 0), Always(), Never()); // From GL_EXT_texture_compression_dxt1 - // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render | - InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never()); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never()); + // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render | + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never()); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never()); // From GL_ANGLE_texture_compression_dxt3 - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), Always(), Never()); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), Always(), Never()); // From GL_ANGLE_texture_compression_dxt5 - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), Always(), Never()); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), Always(), Never()); + + // From GL_ETC1_RGB8_OES + InsertFormatMapping(&map, GL_ETC1_RGB8_OES, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), Always(), Never(), VersionOrExts(3, 0, "GL_ETC1_RGB8_OES"), Always(), Never()); + // clang-format on return map; @@ -372,6 +376,35 @@ static GLenum GetNativeFormat(const FunctionsGL *functions, return result; } +static GLenum GetNativeCompressedFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format) +{ + GLenum result = format; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + if (format == GL_ETC1_RGB8_OES) + { + // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression + // format is forwards compatible so just use the ETC2 format. + result = GL_COMPRESSED_RGB8_ETC2; + } + } + + if (functions->isAtLeastGLES(gl::Version(3, 0))) + { + if (format == GL_ETC1_RGB8_OES) + { + // Pass GL_COMPRESSED_RGB8_ETC2 as the target format in ES3 and higher because it + // becomes a core format. + result = GL_COMPRESSED_RGB8_ETC2; + } + } + + return result; +} + static GLenum GetNativeType(const FunctionsGL *functions, const WorkaroundsGL &workarounds, GLenum type) @@ -429,7 +462,7 @@ CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *function GLenum internalFormat) { CompressedTexImageFormat result; - result.internalFormat = internalFormat; + result.internalFormat = GetNativeCompressedFormat(functions, workarounds, internalFormat); return result; } @@ -438,7 +471,7 @@ CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *fu GLenum format) { CompressedTexSubImageFormat result; - result.format = format; + result.format = GetNativeCompressedFormat(functions, workarounds, format); return result; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp index 1d2d073ea8e..b3fa1e29941 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp @@ -21,6 +21,18 @@ namespace rx { +static int IgnoreX11Errors(Display *, XErrorEvent *) +{ + return 0; +} + +SwapControlData::SwapControlData() + : targetSwapInterval(0), + maxSwapInterval(-1), + currentSwapInterval(-1) +{ +} + class FunctionsGLGLX : public FunctionsGL { public: @@ -45,10 +57,18 @@ class FunctionsGLGLX : public FunctionsGL DisplayGLX::DisplayGLX() : DisplayGL(), mFunctionsGL(nullptr), + mRequestedVisual(-1), mContextConfig(nullptr), mContext(nullptr), mDummyPbuffer(0), mUsesNewXDisplay(false), + mIsMesa(false), + mHasMultisample(false), + mHasARBCreateContext(false), + mSwapControl(SwapControl::Absent), + mMinSwapInterval(0), + mMaxSwapInterval(0), + mCurrentSwapInterval(-1), mEGLDisplay(nullptr) { } @@ -61,6 +81,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display) { mEGLDisplay = display; Display *xDisplay = display->getNativeDisplayId(); + const auto &attribMap = display->getAttributeMap(); // ANGLE_platform_angle allows the creation of a default display // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open @@ -81,29 +102,79 @@ egl::Error DisplayGLX::initialize(egl::Display *display) return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str()); } - // Check we have the needed extensions + mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample"); + mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context"); + + // Choose the swap_control extension to use, if any. + // The EXT version is better as it allows glXSwapInterval to be called per + // window, while we'll potentially need to change the swap interval on each + // swap buffers when using the SGI or MESA versions. + if (mGLX.hasExtension("GLX_EXT_swap_control")) + { + mSwapControl = SwapControl::EXT; + + // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just + // set default values. + mMinSwapInterval = 0; + mMaxSwapInterval = 4; + } + else if (mGLX.hasExtension("GLX_MESA_swap_control")) + { + // If we have the Mesa or SGI extension, assume that you can at least set + // a swap interval of 0 or 1. + mSwapControl = SwapControl::Mesa; + mMinSwapInterval = 0; + mMinSwapInterval = 1; + } + else if (mGLX.hasExtension("GLX_SGI_swap_control")) + { + mSwapControl = SwapControl::SGI; + mMinSwapInterval = 0; + mMinSwapInterval = 1; + } + else + { + mSwapControl = SwapControl::Absent; + mMinSwapInterval = 1; + mMinSwapInterval = 1; + } + + if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE)) { - if (mGLX.minorVersion == 3 && !mGLX.hasExtension("GLX_ARB_multisample")) + mRequestedVisual = attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1); + + // There is no direct way to get the GLXFBConfig matching an X11 visual ID + // so we have to iterate over all the GLXFBConfigs to find the right one. + int nConfigs; + int attribList[] = { + None, + }; + glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs); + + for (int i = 0; i < nConfigs; ++i) { - return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_multisample."); + if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual) + { + mContextConfig = allConfigs[i]; + break; + } } - // Require ARB_create_context which has been supported since Mesa 9 unconditionnaly - // and is present in Mesa 8 in an almost always on compile flag. Also assume proprietary - // drivers have it. - if (!mGLX.hasExtension("GLX_ARB_create_context")) + XFree(allConfigs); + + if (mContextConfig == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_create_context."); + return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested."); } } - - // When glXMakeCurrent is called, the context and the surface must be - // compatible which in glX-speak means that their config have the same - // color buffer type, are both RGBA or ColorIndex, and their buffers have - // the same depth, if they exist. - // Since our whole EGL implementation is backed by only one GL context, this - // context must be compatible with all the GLXFBConfig corresponding to the - // EGLconfigs that we will be exposing. + else { + // When glXMakeCurrent is called, the context and the surface must be + // compatible which in glX-speak means that their config have the same + // color buffer type, are both RGBA or ColorIndex, and their buffers have + // the same depth, if they exist. + // Since our whole EGL implementation is backed by only one GL context, this + // context must be compatible with all the GLXFBConfig corresponding to the + // EGLconfigs that we will be exposing. int nConfigs; int attribList[] = { @@ -127,7 +198,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display) GLX_CONFIG_CAVEAT, GLX_NONE, None }; - glx::FBConfig* candidates = mGLX.chooseFBConfig(attribList, &nConfigs); + glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs); if (nConfigs == 0) { XFree(candidates); @@ -137,7 +208,27 @@ egl::Error DisplayGLX::initialize(egl::Display *display) XFree(candidates); } - mContext = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, nullptr); + if (mHasARBCreateContext) + { + mContext = initializeContext(mContextConfig, display->getAttributeMap()); + } + else + { + XVisualInfo visualTemplate; + visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID); + + int numVisuals = 0; + XVisualInfo *visuals = XGetVisualInfo(xDisplay, VisualIDMask, &visualTemplate, &numVisuals); + if (numVisuals <= 0) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Could not get the visual info from the fb config"); + } + ASSERT(numVisuals == 1); + + mContext = mGLX.createContext(&visuals[0], nullptr, true); + XFree(visuals); + } if (!mContext) { return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context."); @@ -146,11 +237,20 @@ egl::Error DisplayGLX::initialize(egl::Display *display) // FunctionsGL and DisplayGL need to make a few GL calls, for example to // query the version of the context so we need to make the context current. // glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer - // (of size 0, 0) for the duration of these calls. - - // to query things like limits. Ideally we would want to unset the current context - // and destroy the pbuffer before going back to the application but this is TODO - mDummyPbuffer = mGLX.createPbuffer(mContextConfig, nullptr); + // (of size 1, 1) for the duration of these calls. + // Ideally we would want to unset the current context and destroy the pbuffer + // before going back to the application but this is TODO + // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver + // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we + // use (1, 1) instead. + + int dummyPbufferAttribs[] = + { + GLX_PBUFFER_WIDTH, 1, + GLX_PBUFFER_HEIGHT, 1, + None, + }; + mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs); if (!mDummyPbuffer) { return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer."); @@ -166,6 +266,10 @@ egl::Error DisplayGLX::initialize(egl::Display *display) syncXCommands(); + std::string rendererString = + reinterpret_cast<const char*>(mFunctionsGL->getString(GL_RENDERER)); + mIsMesa = rendererString.find("Mesa") != std::string::npos; + return DisplayGL::initialize(display); } @@ -237,15 +341,103 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device) return egl::Error(EGL_BAD_DISPLAY); } +glx::Context DisplayGLX::initializeContext(glx::FBConfig config, + const egl::AttributeMap &eglAttributes) +{ + // Create a context of the requested version, if any. + EGLint requestedMajorVersion = + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinorVersion = + eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE) + { + std::vector<int> contextAttributes; + contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); + contextAttributes.push_back(requestedMajorVersion); + + contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); + contextAttributes.push_back(requestedMinorVersion); + + contextAttributes.push_back(None); + return createContextAttribs(config, contextAttributes); + } + + // It is commonly assumed that glXCreateContextAttrib will create a context + // of the highest version possible but it is not specified in the spec and + // is not true on the Mesa drivers. Instead we try to create a context per + // desktop GL version until we succeed, starting from newer version. + // clang-format off + const gl::Version desktopVersions[] = { + gl::Version(4, 5), + gl::Version(4, 4), + gl::Version(4, 3), + gl::Version(4, 2), + gl::Version(4, 1), + gl::Version(4, 0), + gl::Version(3, 3), + gl::Version(3, 2), + gl::Version(3, 1), + gl::Version(3, 0), + gl::Version(2, 0), + gl::Version(1, 5), + gl::Version(1, 4), + gl::Version(1, 3), + gl::Version(1, 2), + gl::Version(1, 1), + gl::Version(1, 0), + }; + // clang-format on + + bool useProfile = mGLX.hasExtension("GLX_ARB_create_context_profile"); + for (size_t i = 0; i < ArraySize(desktopVersions); ++i) + { + const auto &version = desktopVersions[i]; + + std::vector<int> contextAttributes; + contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); + contextAttributes.push_back(version.major); + + contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); + contextAttributes.push_back(version.minor); + + if (useProfile && version >= gl::Version(3, 2)) + { + contextAttributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); + contextAttributes.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB); + } + + contextAttributes.push_back(None); + auto context = createContextAttribs(config, contextAttributes); + + if (context) + { + return context; + } + } + + return nullptr; +} + egl::ConfigSet DisplayGLX::generateConfigs() const { egl::ConfigSet configs; configIdToGLXConfig.clear(); - bool hasSwapControl = mGLX.hasExtension("GLX_EXT_swap_control"); + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + + int contextRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE); + int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE); + int contextBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE); + int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE); - int contextSamples = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES); - int contextSampleBuffers = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS); + int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE); + int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE); + + int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0; + int contextSampleBuffers = + mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0; int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE); int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE); @@ -273,6 +465,14 @@ egl::ConfigSet DisplayGLX::generateConfigs() const config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE); config.nativeRenderable = EGL_TRUE; + // When a visual ID has been specified with EGL_ANGLE_x11_visual we should + // only return configs with this visual: it will maximize performance by avoid + // blits in the driver when showing the window on the screen. + if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual) + { + continue; + } + // Buffer sizes config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE); config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE); @@ -282,11 +482,19 @@ egl::ConfigSet DisplayGLX::generateConfigs() const config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE); // We require RGBA8 and the D24S8 (or no DS buffer) - if (config.redSize != 8 || config.greenSize != 8 || config.blueSize != 8 || config.alphaSize != 8) + if (config.redSize != contextRedSize || config.greenSize != contextGreenSize || + config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize) { continue; } - if (!(config.depthSize == 24 && config.stencilSize == 8) && !(config.depthSize == 0 && config.stencilSize == 0)) + // The GLX spec says that it is ok for a whole buffer to not be present + // however the Mesa Intel driver (and probably on other Mesa drivers) + // fails to make current when the Depth stencil doesn't exactly match the + // configuration. + bool hasSameDepthStencil = + config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize; + bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0; + if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil)) { continue; } @@ -298,8 +506,9 @@ egl::ConfigSet DisplayGLX::generateConfigs() const config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize; // Multisample and accumulation buffers - int samples = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES); - int sampleBuffers = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS); + int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0; + int sampleBuffers = + mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0; int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE); int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE); @@ -362,23 +571,16 @@ egl::ConfigSet DisplayGLX::generateConfigs() const (glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) | (glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0); - if (hasSwapControl) - { - // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just set a default value. - config.minSwapInterval = 0; - config.maxSwapInterval = 4; - } - else - { - config.minSwapInterval = 1; - config.maxSwapInterval = 1; - } + config.minSwapInterval = mMinSwapInterval; + config.maxSwapInterval = mMaxSwapInterval; + // TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway config.renderTargetFormat = GL_RGBA8; config.depthStencilFormat = GL_DEPTH24_STENCIL8; - // TODO(cwallez) Fill after determining the GL version we are using and what ES version it supports - config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR; - config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR; + + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.renderableType = config.conformant; + // TODO(cwallez) I have no idea what this is config.matchNativePixmap = EGL_NONE; @@ -445,6 +647,54 @@ void DisplayGLX::syncXCommands() const } } +void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data) +{ + ASSERT(data != nullptr); + + // TODO(cwallez) error checking? + if (mSwapControl == SwapControl::EXT) + { + // Prefer the EXT extension, it gives per-drawable swap intervals, which will + // minimize the number of driver calls. + if (data->maxSwapInterval < 0) + { + unsigned int maxSwapInterval = 0; + mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval); + data->maxSwapInterval = static_cast<int>(maxSwapInterval); + } + + // When the egl configs were generated we had to guess what the max swap interval + // was because we didn't have a window to query it one (and that this max could + // depend on the monitor). This means that the target interval might be higher + // than the max interval and needs to be clamped. + const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval); + if (data->currentSwapInterval != realInterval) + { + mGLX.swapIntervalEXT(drawable, realInterval); + data->currentSwapInterval = realInterval; + } + } + else if (mCurrentSwapInterval != data->targetSwapInterval) + { + // With the Mesa or SGI extensions we can still do per-drawable swap control + // manually but it is more expensive in number of driver calls. + if (mSwapControl == SwapControl::Mesa) + { + mGLX.swapIntervalMESA(data->targetSwapInterval); + } + else if (mSwapControl == SwapControl::Mesa) + { + mGLX.swapIntervalSGI(data->targetSwapInterval); + } + mCurrentSwapInterval = data->targetSwapInterval; + } +} + +bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const +{ + return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId; +} + const FunctionsGL *DisplayGLX::getFunctionsGL() const { return mFunctionsGL; @@ -468,4 +718,15 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const return result; } +glx::Context DisplayGLX::createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const +{ + // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can + // be generated. To prevent these errors from crashing our process, we simply ignore + // them and only look if GLXContext was created. + auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors); + auto context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data()); + XSetErrorHandler(oldErrorHandler); + + return context; +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h index e72d9a90b3a..41a985a9d04 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h @@ -20,6 +20,20 @@ namespace rx class FunctionsGLX; +// State-tracking data for the swap control to allow DisplayGLX to remember per +// drawable information for swap control. +struct SwapControlData +{ + SwapControlData(); + + // Set by the drawable + int targetSwapInterval; + + // DisplayGLX-side state-tracking + int maxSwapInterval; + int currentSwapInterval; +}; + class DisplayGLX : public DisplayGL { public: @@ -59,25 +73,52 @@ class DisplayGLX : public DisplayGL // between the application's display and ANGLE's one. void syncXCommands() const; + // Depending on the supported GLX extension, swap interval can be set + // globally or per drawable. This function will make sure the drawable's + // swap interval is the one required so that the subsequent swapBuffers + // acts as expected. + void setSwapInterval(glx::Drawable drawable, SwapControlData *data); + + bool isValidWindowVisualId(unsigned long visualId) const; + private: const FunctionsGL *getFunctionsGL() const override; + glx::Context initializeContext(glx::FBConfig config, const egl::AttributeMap &eglAttributes); + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateCaps(egl::Caps *outCaps) const override; int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const; + glx::Context createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const; FunctionsGL *mFunctionsGL; //TODO(cwallez) yuck, change generateConfigs to be non-const or add a userdata member to egl::Config? mutable std::map<int, glx::FBConfig> configIdToGLXConfig; + EGLint mRequestedVisual; glx::FBConfig mContextConfig; glx::Context mContext; // A pbuffer the context is current on during ANGLE initialization glx::Pbuffer mDummyPbuffer; bool mUsesNewXDisplay; + bool mIsMesa; + bool mHasMultisample; + bool mHasARBCreateContext; + + enum class SwapControl + { + Absent, + EXT, + Mesa, + SGI, + }; + SwapControl mSwapControl; + int mMinSwapInterval; + int mMaxSwapInterval; + int mCurrentSwapInterval; FunctionsGLX mGLX; egl::Display *mEGLDisplay; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md index e5af46aff77..204a4881c49 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md @@ -155,6 +155,37 @@ have the same multisample and accumulation buffers gives the following: 0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None ``` +Mesa Intel driver +----------------- +In GLX, a criterium for context and surface compatibility is that buffers +should have the same depth, if they exist at all in the surface. This means +that it should be possible to make a context with a D24S8 depth-stencil +buffer to a surface without a depth-stencil buffer. This doesn't work on the +Mesa Intel driver. The list before the workaround was the following, with +0x020 being the fbconfig chosen for the context: +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None +0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None +0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +``` + +After the workaround that list becomes the following: +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +``` + Future investigation -------------------- All the non-conformant configs have a multisampled buffer, so it could be interesting @@ -167,3 +198,4 @@ drivers and hardware. The drivers tested were: - the proprietary NVIDIA driver - the proprietary AMD driver + - the open source Intel (Broadwell) Mesa driver diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp index 4dfc4351d8c..a93cea2287c 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp @@ -35,34 +35,42 @@ static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name) struct FunctionsGLX::GLXFunctionTable { GLXFunctionTable() - : destroyContextPtr(nullptr), - makeCurrentPtr(nullptr), - swapBuffersPtr(nullptr), - queryExtensionPtr(nullptr), - queryVersionPtr(nullptr), - waitXPtr(nullptr), - waitGLPtr(nullptr), - queryExtensionsStringPtr(nullptr), - getFBConfigsPtr(nullptr), - chooseFBConfigPtr(nullptr), - getFBConfigAttribPtr(nullptr), - getVisualFromFBConfigPtr(nullptr), - createWindowPtr(nullptr), - destroyWindowPtr(nullptr), - createPbufferPtr(nullptr), - destroyPbufferPtr(nullptr), - queryDrawablePtr(nullptr), - createContextAttribsARBPtr(nullptr), - swapIntervalEXTPtr(nullptr) + : createContextPtr(nullptr), + destroyContextPtr(nullptr), + makeCurrentPtr(nullptr), + swapBuffersPtr(nullptr), + queryExtensionPtr(nullptr), + queryVersionPtr(nullptr), + getCurrentContextPtr(nullptr), + getCurrentDrawablePtr(nullptr), + waitXPtr(nullptr), + waitGLPtr(nullptr), + queryExtensionsStringPtr(nullptr), + getFBConfigsPtr(nullptr), + chooseFBConfigPtr(nullptr), + getFBConfigAttribPtr(nullptr), + getVisualFromFBConfigPtr(nullptr), + createWindowPtr(nullptr), + destroyWindowPtr(nullptr), + createPbufferPtr(nullptr), + destroyPbufferPtr(nullptr), + queryDrawablePtr(nullptr), + createContextAttribsARBPtr(nullptr), + swapIntervalEXTPtr(nullptr), + swapIntervalMESAPtr(nullptr), + swapIntervalSGIPtr(nullptr) { } // GLX 1.0 + PFNGLXCREATECONTEXTPROC createContextPtr; PFNGLXDESTROYCONTEXTPROC destroyContextPtr; PFNGLXMAKECURRENTPROC makeCurrentPtr; PFNGLXSWAPBUFFERSPROC swapBuffersPtr; PFNGLXQUERYEXTENSIONPROC queryExtensionPtr; PFNGLXQUERYVERSIONPROC queryVersionPtr; + PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr; + PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr; PFNGLXWAITXPROC waitXPtr; PFNGLXWAITGLPROC waitGLPtr; @@ -85,6 +93,12 @@ struct FunctionsGLX::GLXFunctionTable // GLX_EXT_swap_control PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr; + + // GLX_MESA_swap_control + PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr; + + // GLX_SGI_swap_control + PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr; }; FunctionsGLX::FunctionsGLX() @@ -149,11 +163,14 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS #endif // GLX 1.0 + GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext); GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext); GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent); GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers); GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension); GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion); + GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext); + GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable); GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX); GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL); @@ -207,17 +224,17 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS { GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB); } - else - { - mFnPtrs->createContextAttribsARBPtr = nullptr; - } if (hasExtension("GLX_EXT_swap_control")) { GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT); } - else + if (hasExtension("GLX_MESA_swap_control")) { - mFnPtrs->swapIntervalEXTPtr = nullptr; + GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA); + } + if (hasExtension("GLX_SGI_swap_control")) + { + GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI); } #undef GET_FNPTR_OR_ERROR @@ -249,6 +266,12 @@ int FunctionsGLX::getScreen() const // GLX functions // GLX 1.0 +glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const +{ + GLXContext shareCtx = reinterpret_cast<GLXContext>(share); + GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct); + return reinterpret_cast<glx::Context>(context); +} void FunctionsGLX::destroyContext(glx::Context context) const { GLXContext ctx = reinterpret_cast<GLXContext>(context); @@ -271,6 +294,16 @@ Bool FunctionsGLX::queryVersion(int *major, int *minor) const { return mFnPtrs->queryVersionPtr(mXDisplay, major, minor); } +glx::Context FunctionsGLX::getCurrentContext() const +{ + GLXContext context = mFnPtrs->getCurrentContextPtr(); + return reinterpret_cast<glx::Context>(context); +} +glx::Drawable FunctionsGLX::getCurrentDrawable() const +{ + GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr(); + return reinterpret_cast<glx::Drawable>(drawable); +} void FunctionsGLX::waitX() const { mFnPtrs->waitXPtr(); @@ -344,4 +377,14 @@ void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals); } +int FunctionsGLX::swapIntervalMESA(int intervals) const +{ + return mFnPtrs->swapIntervalMESAPtr(intervals); +} + +int FunctionsGLX::swapIntervalSGI(int intervals) const +{ + return mFnPtrs->swapIntervalSGIPtr(intervals); +} + } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h index 0afbbbbbd94..a919f4c88b0 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h @@ -37,11 +37,14 @@ class FunctionsGLX PFNGETPROCPROC getProc; // GLX 1.0 + glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const; void destroyContext(glx::Context context) const; Bool makeCurrent(glx::Drawable drawable, glx::Context context) const; void swapBuffers(glx::Drawable drawable) const; Bool queryExtension(int *errorBase, int *event) const; Bool queryVersion(int *major, int *minor) const; + glx::Context getCurrentContext() const; + glx::Drawable getCurrentDrawable() const; void waitX() const; void waitGL() const; @@ -65,6 +68,12 @@ class FunctionsGLX // GLX_EXT_swap_control void swapIntervalEXT(glx::Drawable drawable, int interval) const; + // GLX_MESA_swap_control + int swapIntervalMESA(int interval) const; + + // GLX_SGI_swap_control + int swapIntervalSGI(int interval) const; + private: // So as to isolate GLX from angle we do not include angleutils.h and cannot // use angle::NonCopyable so we replicated it here instead. diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp index d876c6d7a40..1648ecccb56 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp @@ -43,10 +43,16 @@ PbufferSurfaceGLX::~PbufferSurfaceGLX() egl::Error PbufferSurfaceGLX::initialize() { + // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver + // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we + // use (w, 1) or (1, h) instead. + int width = std::max(1, static_cast<int>(mWidth)); + int height = std::max(1, static_cast<int>(mHeight)); + const int attribs[] = { - GLX_PBUFFER_WIDTH, static_cast<int>(mWidth), - GLX_PBUFFER_HEIGHT, static_cast<int>(mHeight), + GLX_PBUFFER_WIDTH, width, + GLX_PBUFFER_HEIGHT, height, GLX_LARGEST_PBUFFER, mLargest, None }; @@ -91,7 +97,7 @@ egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void ** return egl::Error(EGL_SUCCESS); } -egl::Error PbufferSurfaceGLX::bindTexImage(EGLint buffer) +egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer) { UNIMPLEMENTED(); return egl::Error(EGL_SUCCESS); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h index f8d1bf76eae..aae313e293f 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h @@ -36,7 +36,7 @@ class PbufferSurfaceGLX : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp index 4224eebecc8..b4c5fd6c9e2 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp @@ -28,11 +28,10 @@ WindowSurfaceGLX::WindowSurfaceGLX(const FunctionsGLX &glx, mWindow(0), mDisplay(display), mGLX(glx), - mGLXDisplay(*glxDisplay), + mGLXDisplay(glxDisplay), mContext(context), mFBConfig(fbConfig), - mGLXWindow(0), - mMaxSwapInterval(1) + mGLXWindow(0) { } @@ -48,17 +47,31 @@ WindowSurfaceGLX::~WindowSurfaceGLX() XDestroyWindow(mDisplay, mWindow); } - mGLXDisplay.syncXCommands(); + mGLXDisplay->syncXCommands(); } egl::Error WindowSurfaceGLX::initialize() { + // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual + // extension. + { + XWindowAttributes windowAttributes; + XGetWindowAttributes(mDisplay, mParent, &windowAttributes); + unsigned long visualId = windowAttributes.visual->visualid; + + if (!mGLXDisplay->isValidWindowVisualId(visualId)) + { + return egl::Error(EGL_BAD_MATCH, + "The visual of native_window doesn't match the visual given with " + "ANGLE_X11_VISUAL_ID"); + } + } + // The visual of the X window, GLX window and GLX context must match, // however we received a user-created window that can have any visual // and wouldn't work with our GLX context. To work in all cases, we // create a child window with the right visual that covers all of its // parent. - XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig); if (!visualInfo) { @@ -95,18 +108,13 @@ egl::Error WindowSurfaceGLX::initialize() 0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes); mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr); - if (mGLX.hasExtension("GLX_EXT_swap_control")) - { - mGLX.queryDrawable(mGLXWindow, GLX_MAX_SWAP_INTERVAL_EXT, &mMaxSwapInterval); - } - XMapWindow(mDisplay, mWindow); XFlush(mDisplay); XFree(visualInfo); XFreeColormap(mDisplay, colormap); - mGLXDisplay.syncXCommands(); + mGLXDisplay->syncXCommands(); return egl::Error(EGL_SUCCESS); } @@ -140,6 +148,7 @@ egl::Error WindowSurfaceGLX::swap() mGLX.waitX(); } + mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl); mGLX.swapBuffers(mGLXWindow); return egl::Error(EGL_SUCCESS); @@ -157,7 +166,7 @@ egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **v return egl::Error(EGL_SUCCESS); } -egl::Error WindowSurfaceGLX::bindTexImage(EGLint buffer) +egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer) { UNIMPLEMENTED(); return egl::Error(EGL_SUCCESS); @@ -171,12 +180,7 @@ egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer) void WindowSurfaceGLX::setSwapInterval(EGLint interval) { - if (mGLX.hasExtension("GLX_EXT_swap_control")) - { - // TODO(cwallez) error checking? - const int realInterval = std::min(interval, static_cast<int>(mMaxSwapInterval)); - mGLX.swapIntervalEXT(mGLXWindow, realInterval); - } + mSwapControl.targetSwapInterval = interval; } EGLint WindowSurfaceGLX::getWidth() const diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h index f8447abd683..025a83f78de 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h @@ -10,6 +10,7 @@ #define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_ #include "libANGLE/renderer/gl/SurfaceGL.h" +#include "libANGLE/renderer/gl/glx/DisplayGLX.h" #include "libANGLE/renderer/gl/glx/platform_glx.h" namespace rx @@ -36,7 +37,7 @@ class WindowSurfaceGLX : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; @@ -55,12 +56,13 @@ class WindowSurfaceGLX : public SurfaceGL Display *mDisplay; const FunctionsGLX &mGLX; - const DisplayGLX &mGLXDisplay; + DisplayGLX *mGLXDisplay; glx::Context mContext; glx::FBConfig mFBConfig; glx::Window mGLXWindow; - unsigned int mMaxSwapInterval; + + SwapControlData mSwapControl; }; } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h index d54f07124ec..b0ba033c78c 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h @@ -32,6 +32,8 @@ typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx); typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value); typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) (); typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) (); +typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) (); +typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) (); typedef void (*PFNGLXWAITGLPROC) (); typedef void (*PFNGLXWAITXPROC) (); typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h index facacf1a523..a8d9cdec004 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h @@ -111,6 +111,11 @@ #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 #define GLX_CONTEXT_FLAGS_ARB 0x2094 +// GLX_ARB_create_context_profile +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 + // GLX_EXT_texture_from_pixmap #define GLX_TEXTURE_1D_BIT_EXT 0x00000001 #define GLX_TEXTURE_2D_BIT_EXT 0x00000002 diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp index 0209795e6bc..a93f75eb589 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp @@ -111,35 +111,35 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name) { - GLint result; + GLint result = 0; functions->getIntegerv(name, &result); return result; } static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index) { - GLint result[2]; + GLint result[2] = {}; functions->getIntegerv(name, result); return result[index]; } static GLint64 QuerySingleGLInt64(const FunctionsGL *functions, GLenum name) { - GLint64 result; + GLint64 result = 0; functions->getInteger64v(name, &result); return result; } static GLfloat QuerySingleGLFloat(const FunctionsGL *functions, GLenum name) { - GLfloat result; + GLfloat result = 0.0f; functions->getFloatv(name, &result); return result; } static GLfloat QueryGLFloatRange(const FunctionsGL *functions, GLenum name, size_t index) { - GLfloat result[2]; + GLfloat result[2] = {}; functions->getFloatv(name, result); return result[index]; } @@ -478,7 +478,8 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; // Table 6.34, implementation dependent transform feedback limits - if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_transform_feedback") || + if (functions->isAtLeastGL(gl::Version(4, 0)) || + functions->hasGLExtension("GL_ARB_transform_feedback2") || functions->isAtLeastGLES(gl::Version(3, 0))) { caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); @@ -511,6 +512,52 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); } + // Can't support ES3 without texture swizzling + if (!functions->isAtLeastGL(gl::Version(3, 3)) && + !functions->hasGLExtension("GL_ARB_texture_swizzle") && + !functions->hasGLExtension("GL_EXT_texture_swizzle") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + + // Texture swizzling is required to work around the luminance texture format not being + // present in the core profile + if (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) + { + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + } + + // Can't support ES3 without the GLSL packing builtins. We have a workaround for all + // desktop OpenGL versions starting from 3.3 with the bit packing extension. + if (!functions->isAtLeastGL(gl::Version(4, 2)) && + !(functions->isAtLeastGL(gl::Version(3, 2)) && + functions->hasGLExtension("GL_ARB_shader_bit_encoding")) && + !functions->hasGLExtension("GL_ARB_shading_language_packing") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // ES3 needs to support explicit layout location qualifiers, while it might be possible to + // fake them in our side, we currently don't support that. + if (!functions->isAtLeastGL(gl::Version(3, 3)) && + !functions->hasGLExtension("GL_ARB_explicit_attrib_location") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time + // if the max uniform vectors is too large. Artificially limit the maximum until the test is + // updated. + caps->maxVertexUniformVectors = std::min(1024u, caps->maxVertexUniformVectors); + caps->maxVertexUniformComponents = + std::min(caps->maxVertexUniformVectors / 4, caps->maxVertexUniformComponents); + caps->maxFragmentUniformVectors = std::min(1024u, caps->maxFragmentUniformVectors); + caps->maxFragmentUniformComponents = + std::min(caps->maxFragmentUniformVectors / 4, caps->maxFragmentUniformComponents); + // Extension support extensions->setTextureExtensionSupport(*textureCapsMap); extensions->elementIndexUint = functions->standard == STANDARD_GL_DESKTOP || @@ -527,6 +574,11 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers"); extensions->textureStorage = true; extensions->textureFilterAnisotropic = functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLESExtension("GL_EXT_texture_filter_anisotropic"); + extensions->occlusionQueryBoolean = + functions->isAtLeastGL(gl::Version(1, 5)) || + functions->hasGLExtension("GL_ARB_occlusion_query2") || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLESExtension("GL_EXT_occlusion_query_boolean"); extensions->maxTextureAnisotropy = extensions->textureFilterAnisotropic ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0.0f; extensions->fence = functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence"); extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_blend_minmax") || @@ -556,6 +608,9 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM extensions->debugMarker = functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") || functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug"); + + // ANGLE emulates vertex array objects in its GL layer + extensions->vertexArrayObject = true; } void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds) @@ -574,9 +629,12 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround functions->standard == STANDARD_GL_DESKTOP && (vendor == VENDOR_ID_INTEL || vendor == VENDOR_ID_AMD); -#if ANGLE_PLATFORM_APPLE +#if defined(ANGLE_PLATFORM_APPLE) workarounds->doWhileGLSLCausesGPUHang = true; #endif + + workarounds->finishDoesNotCauseQueriesToBeAvailable = + functions->standard == STANDARD_GL_DESKTOP && vendor == VENDOR_ID_NVIDIA; } } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp index 7f293b5c875..284b603891f 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp @@ -233,7 +233,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display) // Request core profile mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - std::vector<int> contextCreationAttibutes; + std::vector<int> contextCreationAttributes; // Don't request a specific version unless the user wants one. WGL will return the highest version // that the driver supports if no version is requested. @@ -242,32 +242,32 @@ egl::Error DisplayWGL::initialize(egl::Display *display) EGLint requestedMinorVersion = displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE) { - contextCreationAttibutes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); - contextCreationAttibutes.push_back(requestedMajorVersion); + contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); + contextCreationAttributes.push_back(requestedMajorVersion); - contextCreationAttibutes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); - contextCreationAttibutes.push_back(requestedMinorVersion); + contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); + contextCreationAttributes.push_back(requestedMinorVersion); } // Set the flag attributes if (flags != 0) { - contextCreationAttibutes.push_back(WGL_CONTEXT_FLAGS_ARB); - contextCreationAttibutes.push_back(flags); + contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB); + contextCreationAttributes.push_back(flags); } // Set the mask attribute if (mask != 0) { - contextCreationAttibutes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB); - contextCreationAttibutes.push_back(mask); + contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB); + contextCreationAttributes.push_back(mask); } // Signal the end of the attributes - contextCreationAttibutes.push_back(0); - contextCreationAttibutes.push_back(0); + contextCreationAttributes.push_back(0); + contextCreationAttributes.push_back(0); - mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttibutes[0]); + mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttributes[0]); } // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp index 6532dfaef97..2cfe6e9eb95 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp @@ -8,6 +8,10 @@ #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" +#include <algorithm> + +#include "common/string_utils.h" + namespace rx { @@ -30,12 +34,15 @@ static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProc } template <typename T> -static void GetWGLExtensionProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL, - const std::string &extensions, const std::string &extensionName, - const std::string &procName, T *outProcAddress) +static void GetWGLExtensionProcAddress(HMODULE glModule, + PFNWGLGETPROCADDRESSPROC getProcAddressWGL, + const std::vector<std::string> &extensions, + const std::string &extensionName, + const std::string &procName, + T *outProcAddress) { T proc = nullptr; - if (extensions.find(extensionName) != std::string::npos) + if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end()) { GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc); } @@ -78,7 +85,15 @@ FunctionsWGL::FunctionsWGL() queryPbufferARB(nullptr), bindTexImageARB(nullptr), releaseTexImageARB(nullptr), - setPbufferAttribARB(nullptr) + setPbufferAttribARB(nullptr), + dxSetResourceShareHandleNV(nullptr), + dxOpenDeviceNV(nullptr), + dxCloseDeviceNV(nullptr), + dxRegisterObjectNV(nullptr), + dxUnregisterObjectNV(nullptr), + dxObjectAccessNV(nullptr), + dxLockObjectsNV(nullptr), + dxUnlockObjectsNV(nullptr) { } @@ -112,15 +127,16 @@ void FunctionsWGL::initialize(HMODULE glModule, HDC context) GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT); GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB); - std::string extensions = ""; + std::string extensionString = ""; if (getExtensionStringEXT) { - extensions = getExtensionStringEXT(); + extensionString = getExtensionStringEXT(); } else if (getExtensionStringARB && context) { - extensions = getExtensionStringARB(context); + extensionString = getExtensionStringARB(context); } + angle::SplitStringAlongWhitespace(extensionString, &extensions); // Load the wgl extension functions by checking if the context supports the extension first @@ -146,6 +162,20 @@ void FunctionsWGL::initialize(HMODULE glModule, HDC context) GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB); GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB); GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB); + + // WGL_NV_DX_interop + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV); } +bool FunctionsWGL::hasExtension(const std::string &ext) const +{ + return std::find(extensions.begin(), extensions.end(), ext) != extensions.end(); +} } diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h index 2f9409a47ac..30cf9ebc0b0 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h @@ -6,6 +6,9 @@ // FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions +#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL +#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL + #include "common/angleutils.h" #include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h" @@ -20,6 +23,10 @@ class FunctionsWGL : angle::NonCopyable // Loads all available wgl functions, may be called multiple times void initialize(HMODULE glModule, HDC context); + // Extension information + std::vector<std::string> extensions; + bool hasExtension(const std::string &ext) const; + // Base WGL functions PFNWGLCOPYCONTEXTPROC copyContext; PFNWGLCREATECONTEXTPROC createContext; @@ -70,6 +77,18 @@ class FunctionsWGL : angle::NonCopyable PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB; PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB; PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB; + + // WGL_NV_DX_interop + PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV; + PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV; + PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV; + PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV; + PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV; + PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV; + PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV; + PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV; }; } + +#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp index 0615c879a0c..440b9934c47 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp @@ -146,7 +146,7 @@ static int GetWGLBufferBindTarget(EGLint buffer) } } -egl::Error PbufferSurfaceWGL::bindTexImage(EGLint buffer) +egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) { if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) { diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h index 3deab4b5cdb..64e4de16c6d 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h @@ -39,7 +39,7 @@ class PbufferSurfaceWGL : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp index 9c898a70d77..4c7e073d6a2 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp @@ -119,7 +119,7 @@ egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **v return egl::Error(EGL_SUCCESS); } -egl::Error WindowSurfaceWGL::bindTexImage(EGLint buffer) +egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) { UNIMPLEMENTED(); return egl::Error(EGL_SUCCESS); diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h index 568db3d5421..5112554cea6 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h @@ -34,7 +34,7 @@ class WindowSurfaceWGL : public SurfaceGL egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp index 1fae5a04ed0..641c3fbc429 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp @@ -8,7 +8,7 @@ #include "libANGLE/renderer/gl/wgl/wgl_utils.h" -#include "libANGLE/renderer/gl/wgl/functionsWGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" namespace rx { |