Commit 29639857 by Jamie Madill Committed by Commit Bot

D3D11: Work around Intel uniform buffers bug.

When copying from a staging buffer to a uniform buffer, the first upload would be incorrect. Work around this by trying to upload directly to a uniform buffer on the first BufferSubData call. BUG=chromium:593024 Change-Id: I0df3a1422b962bf3ece5d445f435df01e3544b67 Reviewed-on: https://chromium-review.googlesource.com/368774Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 4a9cd800
......@@ -44,45 +44,33 @@ const std::string &Buffer::getLabel() const
return mLabel;
}
Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
Error Buffer::bufferData(GLenum target, const void *data, GLsizeiptr size, GLenum usage)
{
gl::Error error = mBuffer->setData(data, size, usage);
if (error.isError())
{
return error;
}
ANGLE_TRY(mBuffer->setData(target, data, size, usage));
mIndexRangeCache.clear();
mUsage = usage;
mSize = size;
return error;
return NoError();
}
Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
Error Buffer::bufferSubData(GLenum target, const void *data, GLsizeiptr size, GLintptr offset)
{
gl::Error error = mBuffer->setSubData(data, size, offset);
if (error.isError())
{
return error;
}
ANGLE_TRY(mBuffer->setSubData(target, data, size, offset));
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
return error;
return NoError();
}
Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
if (error.isError())
{
return error;
}
ANGLE_TRY(mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size));
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
return error;
return NoError();
}
Error Buffer::map(GLenum access)
......@@ -178,18 +166,14 @@ Error Buffer::getIndexRange(GLenum type,
{
if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
{
return gl::Error(GL_NO_ERROR);
return NoError();
}
Error error = mBuffer->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange);
if (error.isError())
{
return error;
}
ANGLE_TRY(mBuffer->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange));
mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
return Error(GL_NO_ERROR);
return NoError();
}
} // namespace gl
......@@ -34,8 +34,8 @@ class Buffer final : public RefCountObject, public LabeledObject
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
Error bufferData(GLenum target, const void *data, GLsizeiptr size, GLenum usage);
Error bufferSubData(GLenum target, const void *data, GLsizeiptr size, GLintptr offset);
Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
Error map(GLenum access);
Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
......
......@@ -3430,4 +3430,23 @@ void Context::popDebugGroup()
mGLState.getDebug().popGroup();
}
void Context::bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
{
Buffer *buffer = mGLState.getTargetBuffer(target);
ASSERT(buffer);
handleError(buffer->bufferData(target, data, size, usage));
}
void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
{
if (data == nullptr)
{
return;
}
Buffer *buffer = mGLState.getTargetBuffer(target);
ASSERT(buffer);
handleError(buffer->bufferSubData(target, data, size, offset));
}
} // namespace gl
......@@ -567,6 +567,9 @@ class Context final : public ValidationContext
GLint components,
const GLfloat *coeffs);
void bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
void bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
void handleError(const Error &error) override;
GLenum getError();
......
......@@ -23,8 +23,8 @@ class BufferImpl : angle::NonCopyable
public:
virtual ~BufferImpl() { }
virtual gl::Error setData(const void *data, size_t size, GLenum usage) = 0;
virtual gl::Error setSubData(const void *data, size_t size, size_t offset) = 0;
virtual gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) = 0;
virtual gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) = 0;
virtual gl::Error copySubData(BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
......
......@@ -21,8 +21,8 @@ class MockBufferImpl : public BufferImpl
public:
~MockBufferImpl() { destructor(); }
MOCK_METHOD3(setData, gl::Error(const void*, size_t, GLenum));
MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
MOCK_METHOD4(setData, gl::Error(GLenum, const void *, size_t, GLenum));
MOCK_METHOD4(setSubData, gl::Error(GLenum, const void *, size_t, size_t));
MOCK_METHOD4(copySubData, gl::Error(BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
......
......@@ -43,7 +43,7 @@ enum class CopyResult
namespace gl_d3d11
{
D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
{
bool readBit = ((access & GL_MAP_READ_BIT) != 0);
bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
......@@ -59,7 +59,8 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
}
else if (writeBit && !readBit)
{
return D3D11_MAP_WRITE;
// Special case for uniform storage - we only allow full buffer updates.
return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
}
else if (writeBit && readBit)
{
......@@ -88,7 +89,7 @@ class Buffer11::BufferStorage : angle::NonCopyable
size_t getSize() const { return mBufferSize; }
void setDataRevision(DataRevision rev) { mRevision = rev; }
virtual bool isMappable() const = 0;
virtual bool isMappable(GLbitfield access) const = 0;
virtual gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
......@@ -123,7 +124,7 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
const angle::BroadcastChannel *onStorageChanged);
~NativeStorage() override;
bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
bool isMappable(GLbitfield access) const override;
ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
......@@ -157,7 +158,7 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
EmulatedIndexedStorage(Renderer11 *renderer);
~EmulatedIndexedStorage() override;
bool isMappable() const override { return true; }
bool isMappable(GLbitfield access) const override { return true; }
gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
......@@ -190,7 +191,7 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage
explicit PackStorage(Renderer11 *renderer);
~PackStorage() override;
bool isMappable() const override { return true; }
bool isMappable(GLbitfield access) const override { return true; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
size_t size,
......@@ -225,7 +226,7 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
explicit SystemMemoryStorage(Renderer11 *renderer);
~SystemMemoryStorage() override {}
bool isMappable() const override { return true; }
bool isMappable(GLbitfield access) const override { return true; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
size_t size,
......@@ -272,10 +273,10 @@ Buffer11::~Buffer11()
mRenderer->onBufferDelete(this);
}
gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage)
{
updateD3DBufferUsage(usage);
ANGLE_TRY(setSubData(data, size, 0));
ANGLE_TRY(setSubData(target, data, size, 0));
return gl::NoError();
}
......@@ -299,16 +300,20 @@ gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStor
return GetAs<SystemMemoryStorage>(storage);
}
gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
gl::Error Buffer11::setSubData(GLenum target, const void *data, size_t size, size_t offset)
{
size_t requiredSize = size + offset;
if (data && size > 0)
{
// Use system memory storage for dynamic buffers.
// Try using a constant storage for constant buffers
BufferStorage *writeBuffer = nullptr;
if (supportsDirectBinding())
if (target == GL_UNIFORM_BUFFER && offset == 0 && size >= mSize)
{
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), writeBuffer);
}
else if (supportsDirectBinding())
{
ANGLE_TRY_RESULT(getStagingStorage(), writeBuffer);
}
......@@ -363,11 +368,12 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
// If copying to/from a pixel pack buffer, we must have a staging or
// pack buffer partner, because other native buffers can't be mapped
if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable(GL_MAP_READ_BIT))
{
ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(), copySource);
}
else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK &&
!copyDest->isMappable(GL_MAP_WRITE_BIT))
{
ANGLE_TRY_RESULT(getStagingStorage(), copyDest);
}
......@@ -746,7 +752,7 @@ gl::Error Buffer11::updateBufferStorage(BufferStorage *storage,
// data directly. If we're already using a staging buffer we're fine.
if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
storage->getUsage() != BUFFER_USAGE_STAGING &&
(!latestBuffer->isMappable() || !storage->isMappable()))
(!latestBuffer->isMappable(GL_MAP_READ_BIT) || !storage->isMappable(GL_MAP_WRITE_BIT)))
{
NativeStorage *stagingBuffer = nullptr;
ANGLE_TRY_RESULT(getStagingStorage(), stagingBuffer);
......@@ -852,7 +858,7 @@ Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
{
ASSERT(isMappable());
ASSERT(isMappable(GL_MAP_WRITE_BIT));
uint8_t *writePointer = nullptr;
ANGLE_TRY(map(offset, size, GL_MAP_WRITE_BIT, &writePointer));
......@@ -876,6 +882,17 @@ Buffer11::NativeStorage::~NativeStorage()
SafeRelease(mNativeStorage);
}
bool Buffer11::NativeStorage::isMappable(GLbitfield access) const
{
if ((access & GL_MAP_READ_BIT) != 0)
{
// Read is more exclusive than write mappability.
return (mUsage == BUFFER_USAGE_STAGING);
}
ASSERT((access & GL_MAP_WRITE_BIT) != 0);
return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM);
}
// Returns true if it recreates the direct buffer
gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferStorage *source,
size_t sourceOffset,
......@@ -897,7 +914,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferSto
if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
{
ASSERT(source->isMappable());
ASSERT(source->isMappable(GL_MAP_READ_BIT));
uint8_t *sourcePointer = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourcePointer));
......@@ -1055,11 +1072,11 @@ gl::Error Buffer11::NativeStorage::map(size_t offset,
GLbitfield access,
uint8_t **mapPointerOut)
{
ASSERT(mUsage == BUFFER_USAGE_STAGING);
ASSERT(isMappable(access));
D3D11_MAPPED_SUBRESOURCE mappedResource;
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
......@@ -1076,7 +1093,7 @@ gl::Error Buffer11::NativeStorage::map(size_t offset,
void Buffer11::NativeStorage::unmap()
{
ASSERT(mUsage == BUFFER_USAGE_STAGING);
ASSERT(isMappable(GL_MAP_WRITE_BIT) || isMappable(GL_MAP_READ_BIT));
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
context->Unmap(mNativeStorage, 0);
}
......@@ -1215,7 +1232,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage(
size_t size,
size_t destOffset)
{
ASSERT(source->isMappable());
ASSERT(source->isMappable(GL_MAP_READ_BIT));
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mMemoryBuffer.size());
......@@ -1271,7 +1288,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(BufferStora
// We copy through a staging buffer when drawing with a pack buffer, or for other cases where we
// access the pack buffer
ASSERT(source->isMappable() && source->getUsage() == BUFFER_USAGE_STAGING);
ASSERT(source->isMappable(GL_MAP_READ_BIT) && source->getUsage() == BUFFER_USAGE_STAGING);
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mMemoryBuffer.size());
......@@ -1394,7 +1411,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(Buf
size_t size,
size_t destOffset)
{
ASSERT(source->isMappable());
ASSERT(source->isMappable(GL_MAP_READ_BIT));
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mSystemCopy.size());
......
......@@ -68,8 +68,8 @@ class Buffer11 : public BufferD3D
void invalidateStaticData() override;
// BufferImpl implementation
gl::Error setData(const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(const void *data, size_t size, size_t offset) override;
gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
gl::Error copySubData(BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
......
......@@ -22,7 +22,7 @@ Buffer9::~Buffer9()
mSize = 0;
}
gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
gl::Error Buffer9::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage)
{
if (size > mMemory.size())
{
......@@ -51,7 +51,7 @@ gl::Error Buffer9::getData(const uint8_t **outData)
return gl::Error(GL_NO_ERROR);
}
gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
gl::Error Buffer9::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset)
{
if (offset + size > mMemory.size())
{
......
......@@ -29,13 +29,16 @@ class Buffer9 : public BufferD3D
gl::Error getData(const uint8_t **outData) override;
// BufferImpl implementation
virtual gl::Error setData(const void* data, size_t size, GLenum usage);
virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
virtual gl::Error map(GLenum access, GLvoid **mapPtr);
virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
virtual gl::Error unmap(GLboolean *result);
virtual gl::Error markTransformFeedbackUsage();
gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
gl::Error copySubData(BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size) override;
gl::Error map(GLenum access, GLvoid **mapPtr) override;
gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
gl::Error unmap(GLboolean *result) override;
gl::Error markTransformFeedbackUsage() override;
private:
MemoryBuffer mMemory;
......
......@@ -53,7 +53,7 @@ BufferGL::~BufferGL()
mBufferID = 0;
}
gl::Error BufferGL::setData(const void* data, size_t size, GLenum usage)
gl::Error BufferGL::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage)
{
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
mFunctions->bufferData(DestBufferOperationTarget, size, data, usage);
......@@ -76,7 +76,7 @@ gl::Error BufferGL::setData(const void* data, size_t size, GLenum usage)
return gl::Error(GL_NO_ERROR);
}
gl::Error BufferGL::setSubData(const void* data, size_t size, size_t offset)
gl::Error BufferGL::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset)
{
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
mFunctions->bufferSubData(DestBufferOperationTarget, offset, size, data);
......
......@@ -24,8 +24,8 @@ class BufferGL : public BufferImpl
BufferGL(const FunctionsGL *functions, StateManagerGL *stateManager);
~BufferGL() override;
gl::Error setData(const void* data, size_t size, GLenum usage) override;
gl::Error setSubData(const void* data, size_t size, size_t offset) override;
gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) override;
gl::Error map(GLenum access, GLvoid **mapPtr) override;
gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
......
......@@ -22,13 +22,13 @@ BufferVk::~BufferVk()
{
}
gl::Error BufferVk::setData(const void *data, size_t size, GLenum usage)
gl::Error BufferVk::setData(GLenum target, const void *data, size_t size, GLenum usage)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
}
gl::Error BufferVk::setSubData(const void *data, size_t size, size_t offset)
gl::Error BufferVk::setSubData(GLenum target, const void *data, size_t size, size_t offset)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
......
......@@ -21,8 +21,8 @@ class BufferVk : public BufferImpl
BufferVk();
~BufferVk() override;
gl::Error setData(const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(const void *data, size_t size, size_t offset) override;
gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
gl::Error copySubData(BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
......
......@@ -233,7 +233,7 @@ bool ValidFramebufferTarget(GLenum target)
}
}
bool ValidBufferTarget(const Context *context, GLenum target)
bool ValidBufferTarget(const ValidationContext *context, GLenum target)
{
switch (target)
{
......
......@@ -37,7 +37,7 @@ bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target);
bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target);
bool ValidFramebufferTarget(GLenum target);
bool ValidBufferTarget(const Context *context, GLenum target);
bool ValidBufferTarget(const ValidationContext *context, GLenum target);
bool ValidBufferParameter(const Context *context, GLenum pname);
bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level);
bool ValidImageSizeParameters(const Context *context,
......
......@@ -3325,6 +3325,111 @@ bool ValidateCreateShader(Context *context, GLenum type)
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
return true;
}
bool ValidateBufferData(ValidationContext *context,
GLenum target,
GLsizeiptr size,
const GLvoid *data,
GLenum usage)
{
if (size < 0)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
switch (usage)
{
case GL_STREAM_DRAW:
case GL_STATIC_DRAW:
case GL_DYNAMIC_DRAW:
break;
case GL_STREAM_READ:
case GL_STREAM_COPY:
case GL_STATIC_READ:
case GL_STATIC_COPY:
case GL_DYNAMIC_READ:
case GL_DYNAMIC_COPY:
if (context->getClientMajorVersion() < 3)
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
if (!ValidBufferTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
Buffer *buffer = context->getGLState().getTargetBuffer(target);
if (!buffer)
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
}
return true;
}
bool ValidateBufferSubData(ValidationContext *context,
GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid *data)
{
if (size < 0 || offset < 0)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (!ValidBufferTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
Buffer *buffer = context->getGLState().getTargetBuffer(target);
if (!buffer)
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
}
if (buffer->isMapped())
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
}
// Check for possible overflow of size + offset
angle::CheckedNumeric<size_t> checkedSize(size);
checkedSize += offset;
if (!checkedSize.IsValid())
{
context->handleError(Error(GL_OUT_OF_MEMORY));
return false;
}
if (size + offset > buffer->getSize())
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
return true;
}
......
......@@ -306,6 +306,16 @@ bool ValidateCopySubTextureCHROMIUM(Context *context,
GLboolean unpackUnmultiplyAlpha);
bool ValidateCreateShader(Context *context, GLenum type);
bool ValidateBufferData(ValidationContext *context,
GLenum target,
GLsizeiptr size,
const GLvoid *data,
GLenum usage);
bool ValidateBufferSubData(ValidationContext *context,
GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid *data);
} // namespace gl
......
......@@ -427,57 +427,12 @@ void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
Context *context = GetValidGlobalContext();
if (context)
{
if (size < 0)
if (!context->skipValidation() && !ValidateBufferData(context, target, size, data, usage))
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
switch (usage)
{
case GL_STREAM_DRAW:
case GL_STATIC_DRAW:
case GL_DYNAMIC_DRAW:
break;
case GL_STREAM_READ:
case GL_STREAM_COPY:
case GL_STATIC_READ:
case GL_STATIC_COPY:
case GL_DYNAMIC_READ:
case GL_DYNAMIC_COPY:
if (context->getClientMajorVersion() < 3)
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (!ValidBufferTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
Buffer *buffer = context->getGLState().getTargetBuffer(target);
if (!buffer)
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
}
Error error = buffer->bufferData(data, size, usage);
if (error.isError())
{
context->handleError(error);
return;
}
context->bufferData(target, size, data, usage);
}
}
......@@ -489,58 +444,13 @@ void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
Context *context = GetValidGlobalContext();
if (context)
{
if (size < 0 || offset < 0)
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
if (!ValidBufferTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
Buffer *buffer = context->getGLState().getTargetBuffer(target);
if (!buffer)
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
}
if (buffer->isMapped())
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
}
// Check for possible overflow of size + offset
angle::CheckedNumeric<size_t> checkedSize(size);
checkedSize += offset;
if (!checkedSize.IsValid())
{
context->handleError(Error(GL_OUT_OF_MEMORY));
return;
}
if (size + offset > buffer->getSize())
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
if (data == NULL)
if (!context->skipValidation() &&
!ValidateBufferSubData(context, target, offset, size, data))
{
return;
}
Error error = buffer->bufferSubData(data, size, offset);
if (error.isError())
{
context->handleError(error);
return;
}
context->bufferSubData(target, offset, size, data);
}
}
......
......@@ -37,7 +37,8 @@ class D3D11EmulatedIndexedBufferTest : public ANGLETest
mSourceBuffer = new rx::Buffer11(mRenderer);
GLfloat testData[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
gl::Error error = mSourceBuffer->setData(testData, sizeof(testData), GL_STATIC_DRAW);
gl::Error error =
mSourceBuffer->setData(GL_ARRAY_BUFFER, testData, sizeof(testData), GL_STATIC_DRAW);
ASSERT_FALSE(error.isError());
mTranslatedAttribute.baseOffset = 0;
......
......@@ -77,13 +77,6 @@ class UniformBufferTest : public ANGLETest
// Basic UBO functionality.
TEST_P(UniformBufferTest, Simple)
{
// TODO(jmadill): Figure out why this fails on Intel.
if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
std::cout << "Test skipped on Intel." << std::endl;
return;
}
glClear(GL_COLOR_BUFFER_BIT);
float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
......@@ -104,13 +97,6 @@ TEST_P(UniformBufferTest, Simple)
// The second step renders a color from a UBO with a non-zero offset.
TEST_P(UniformBufferTest, UniformBufferRange)
{
// TODO(jmadill): Figure out why this fails on Intel.
if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
std::cout << "Test skipped on Intel." << std::endl;
return;
}
int px = getWindowWidth() / 2;
int py = getWindowHeight() / 2;
......@@ -182,13 +168,6 @@ TEST_P(UniformBufferTest, UniformBufferRange)
// Test uniform block bindings.
TEST_P(UniformBufferTest, UniformBufferBindings)
{
// TODO(jmadill): Figure out why this fails on Intel.
if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
std::cout << "Test skipped on Intel." << std::endl;
return;
}
int px = getWindowWidth() / 2;
int py = getWindowHeight() / 2;
......@@ -245,11 +224,10 @@ TEST_P(UniformBufferTest, UnboundUniformBuffer)
// https://code.google.com/p/angleproject/issues/detail?id=965
TEST_P(UniformBufferTest, UniformBufferManyUpdates)
{
// TODO(jmadill): Figure out why this fails on Intel.
if (IsIntel() && (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE))
// TODO(jmadill): Figure out why this fails on Intel OpenGL.
if (IsIntel() && IsOpenGL())
{
std::cout << "Test skipped on Intel." << std::endl;
std::cout << "Test skipped on Intel OpenGL." << std::endl;
return;
}
......@@ -286,13 +264,6 @@ TEST_P(UniformBufferTest, UniformBufferManyUpdates)
// Use a large number of buffer ranges (compared to the actual size of the UBO)
TEST_P(UniformBufferTest, ManyUniformBufferRange)
{
// TODO(jmadill): Figure out why this fails on Intel.
if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
std::cout << "Test skipped on Intel." << std::endl;
return;
}
int px = getWindowWidth() / 2;
int py = getWindowHeight() / 2;
......
......@@ -82,7 +82,7 @@ class MockBufferD3D : public rx::BufferD3D
}
// BufferImpl
gl::Error setData(const void *data, size_t size, GLenum) override
gl::Error setData(GLenum target, const void *data, size_t size, GLenum) override
{
mData.resize(size);
if (data && size > 0)
......@@ -92,7 +92,7 @@ class MockBufferD3D : public rx::BufferD3D
return gl::Error(GL_NO_ERROR);
}
MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
MOCK_METHOD4(setSubData, gl::Error(GLenum, const void *, size_t, size_t));
MOCK_METHOD4(copySubData, gl::Error(BufferImpl*, GLintptr, GLintptr, GLsizeiptr));
MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
......@@ -152,7 +152,8 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest()
{
indexData[index] = static_cast<GLushort>(index);
}
mIndexBuffer.bufferData(&indexData[0], indexData.size() * sizeof(GLushort), GL_STATIC_DRAW);
mIndexBuffer.bufferData(GL_ARRAY_BUFFER, &indexData[0], indexData.size() * sizeof(GLushort),
GL_STATIC_DRAW);
}
void IndexDataManagerPerfTest::step()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment