Commit 53a36004 by Jamie Madill

Revert "Re-land "D3D11: Implement dirty bits for VertexArray11."""

Seems to make the following dEQP test flaky: dEQP-GLES3.functional.lifetime.attach.deleted_output.buffer_transform_feedback doesn't show up on every bot test, but run it a few times and it'll flake. Reverting while I investigate. BUG=angleproject:1327 This reverts commit 3477f3a6. Change-Id: Ic23a392526f5f6e107cf0aa06448389804d6b208 Reviewed-on: https://chromium-review.googlesource.com/337961Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 76d17b27
......@@ -29,7 +29,9 @@ VertexArray::Data::~Data()
}
VertexArray::VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs)
: mId(id), mData(maxAttribs), mVertexArray(factory->createVertexArray(mData))
: mId(id),
mVertexArray(factory->createVertexArray(mData)),
mData(maxAttribs)
{
}
......
......@@ -114,10 +114,10 @@ class VertexArray final : public LabeledObject
private:
GLuint mId;
rx::VertexArrayImpl *mVertexArray;
Data mData;
DirtyBits mDirtyBits;
rx::VertexArrayImpl *mVertexArray;
};
}
......
......@@ -161,13 +161,13 @@ void BufferD3D::invalidateStaticData()
// Creates static buffers if sufficient used data has been left unmodified
void BufferD3D::promoteStaticUsage(int dataSize)
{
if (mUsage == D3DBufferUsage::DYNAMIC)
if (mStaticVertexBuffers.empty() && !mStaticIndexBuffer)
{
mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * getSize())
{
updateD3DBufferUsage(GL_STATIC_DRAW);
initializeStaticData();
}
}
}
......
......@@ -43,8 +43,8 @@ class BufferD3D : public BufferImpl
StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute);
StaticIndexBufferInterface *getStaticIndexBuffer();
virtual void initializeStaticData();
virtual void invalidateStaticData();
void initializeStaticData();
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
......
......@@ -55,6 +55,7 @@ RendererD3D::~RendererD3D()
void RendererD3D::cleanup()
{
mTranslatedAttribCache.clear();
mScratchMemoryBuffer.resize(0);
for (auto &incompleteTexture : mIncompleteTextures)
{
......@@ -198,7 +199,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
if (!skipDraw(data, mode))
{
ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
ANGLE_TRY(drawArraysImpl(data, mode, count, instances));
if (data.state->isTransformFeedbackActiveUnpaused())
{
......
......@@ -285,6 +285,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
void initializeDebugAnnotator();
gl::DebugAnnotator *mAnnotator;
std::vector<TranslatedAttribute> mTranslatedAttribCache;
bool mPresentPathFastEnabled;
private:
......@@ -304,7 +306,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances) = 0;
virtual gl::Error drawElementsImpl(const gl::Data &data,
......
......@@ -80,7 +80,7 @@ class VertexBufferInterface : angle::NonCopyable
unsigned int getSerial() const;
VertexBuffer *getVertexBuffer() const;
VertexBuffer* getVertexBuffer() const;
protected:
gl::Error discard();
......
......@@ -10,10 +10,9 @@
#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
#include "common/angleutils.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Constants.h"
#include "libANGLE/VertexAttribute.h"
#include "common/angleutils.h"
namespace gl
{
......@@ -48,16 +47,11 @@ struct TranslatedAttribute
{
TranslatedAttribute();
// Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex.
// Can throw an error on integer overflow.
gl::ErrorOrResult<unsigned int> computeOffset(GLint startVertex) const;
bool active;
const gl::VertexAttribute *attribute;
GLenum currentValueType;
unsigned int baseOffset;
bool usesFirstVertexOffset;
unsigned int offset;
unsigned int stride; // 0 means not to advance the read pointer at all
VertexBufferBinding vertexBuffer;
......@@ -90,23 +84,19 @@ class VertexDataManager : angle::NonCopyable
std::vector<TranslatedAttribute> *translatedAttribs,
GLsizei instances);
static void StoreDirectAttrib(TranslatedAttribute *directAttrib);
static void StoreDirectAttrib(TranslatedAttribute *directAttrib, GLint start);
static gl::Error StoreStaticAttrib(TranslatedAttribute *translated,
GLint start,
GLsizei count,
GLsizei instances);
gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs,
const gl::AttributesMask &dynamicAttribsMask,
const std::vector<size_t> &dynamicAttribIndexes,
GLint start,
GLsizei count,
GLsizei instances);
// Promote static usage of dynamic buffers.
static void PromoteDynamicAttribs(const std::vector<TranslatedAttribute> &translatedAttribs,
const gl::AttributesMask &dynamicAttribsMask,
GLsizei count);
gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
TranslatedAttribute *translated,
size_t attribIndex);
......@@ -131,11 +121,13 @@ class VertexDataManager : angle::NonCopyable
GLsizei count,
GLsizei instances);
void unmapStreamingBuffer();
BufferFactoryD3D *const mFactory;
StreamingVertexBufferInterface *mStreamingBuffer;
std::vector<CurrentValueState> mCurrentValueCache;
gl::AttributesMask mDynamicAttribsMaskCache;
std::vector<size_t> mDynamicAttributeIndexesCache;
};
} // namespace rx
......
......@@ -138,7 +138,7 @@ class Buffer11::BufferStorage : angle::NonCopyable
class Buffer11::NativeStorage : public Buffer11::BufferStorage
{
public:
NativeStorage(Renderer11 *renderer, BufferUsage usage, const NotificationSet *onStorageChanged);
NativeStorage(Renderer11 *renderer, BufferUsage usage);
~NativeStorage() override;
bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
......@@ -163,7 +163,6 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
unsigned int bufferSize);
ID3D11Buffer *mNativeStorage;
const NotificationSet *mOnStorageChanged;
};
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
......@@ -178,8 +177,7 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
bool isMappable() const override { return true; }
gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
GLint startVertex);
const TranslatedAttribute &attribute);
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
......@@ -523,8 +521,7 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage)
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
GLint startVertex)
const TranslatedAttribute &attribute)
{
ASSERT(indexInfo);
......@@ -536,8 +533,7 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage);
ID3D11Buffer *nativeStorage = nullptr;
ANGLE_TRY_RESULT(emulatedStorage->getNativeStorage(indexInfo, attribute, startVertex),
nativeStorage);
ANGLE_TRY_RESULT(emulatedStorage->getNativeStorage(indexInfo, attribute), nativeStorage);
return nativeStorage;
}
......@@ -638,7 +634,23 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUs
if (!newStorage)
{
newStorage = allocateStorage(usage);
if (usage == BUFFER_USAGE_PIXEL_PACK)
{
newStorage = new PackStorage(mRenderer);
}
else if (usage == BUFFER_USAGE_SYSTEM_MEMORY)
{
newStorage = new SystemMemoryStorage(mRenderer);
}
else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX)
{
newStorage = new EmulatedIndexedStorage(mRenderer);
}
else
{
// buffer is not allocated, create it
newStorage = new NativeStorage(mRenderer, usage);
}
}
// resize buffer
......@@ -652,23 +664,6 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUs
return newStorage;
}
Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) const
{
switch (usage)
{
case BUFFER_USAGE_PIXEL_PACK:
return new PackStorage(mRenderer);
case BUFFER_USAGE_SYSTEM_MEMORY:
return new SystemMemoryStorage(mRenderer);
case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
return new EmulatedIndexedStorage(mRenderer);
case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
return new NativeStorage(mRenderer, usage, &mDirectBufferDirtyCallbacks);
default:
return new NativeStorage(mRenderer, usage, nullptr);
}
}
gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeStorage(
GLintptr offset,
GLsizeiptr size)
......@@ -682,7 +677,7 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto
if (!cacheEntry->storage)
{
cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM);
cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM);
cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
}
......@@ -811,43 +806,8 @@ bool Buffer11::supportsDirectBinding() const
{
// Do not support direct buffers for dynamic data. The streaming buffer
// offers better performance for data which changes every frame.
return (mUsage == D3DBufferUsage::STATIC);
}
void Buffer11::initializeStaticData()
{
BufferD3D::initializeStaticData();
// Notify when static data changes.
mStaticBufferDirtyCallbacks.signal();
}
void Buffer11::invalidateStaticData()
{
BufferD3D::invalidateStaticData();
// Notify when static data changes.
mStaticBufferDirtyCallbacks.signal();
}
void Buffer11::addStaticBufferDirtyCallback(const NotificationCallback *callback)
{
mStaticBufferDirtyCallbacks.add(callback);
}
void Buffer11::removeStaticBufferDirtyCallback(const NotificationCallback *callback)
{
mStaticBufferDirtyCallbacks.remove(callback);
}
void Buffer11::addDirectBufferDirtyCallback(const NotificationCallback *callback)
{
mDirectBufferDirtyCallbacks.add(callback);
}
void Buffer11::removeDirectBufferDirtyCallback(const NotificationCallback *callback)
{
mDirectBufferDirtyCallbacks.remove(callback);
// Check for absence of static buffer interfaces to detect dynamic data.
return (!mStaticVertexBuffers.empty() && mStaticIndexBuffer);
}
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
......@@ -869,10 +829,8 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s
return gl::NoError();
}
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
BufferUsage usage,
const NotificationSet *onStorageChanged)
: BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged)
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage)
: BufferStorage(renderer, usage), mNativeStorage(nullptr)
{
}
......@@ -987,12 +945,6 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
mBufferSize = bufferDesc.ByteWidth;
// Notify that the storage has changed.
if (mOnStorageChanged)
{
mOnStorageChanged->signal();
}
return gl::NoError();
}
......@@ -1098,8 +1050,7 @@ Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage()
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeStorage(
SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
GLint startVertex)
const TranslatedAttribute &attribute)
{
// If a change in the indices applied from the last draw call is detected, then the emulated
// indexed buffer needs to be invalidated. After invalidation, the change detected flag should
......@@ -1141,12 +1092,9 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeSto
if (!mNativeStorage)
{
unsigned int offset = 0;
ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset);
// Expand the memory storage upon request and cache the results.
unsigned int expandedDataSize =
static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + attribute.offset);
MemoryBuffer expandedData;
if (!expandedData.resize(expandedDataSize))
{
......@@ -1163,7 +1111,7 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeSto
// Ensure that we start in the correct place for the emulated data copy operation to
// maintain offset behaviors.
curr += offset;
curr += attribute.offset;
ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>;
......
......@@ -13,7 +13,6 @@
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl
{
......@@ -64,9 +63,9 @@ class Buffer11 : public BufferD3D
virtual ~Buffer11();
gl::ErrorOrResult<ID3D11Buffer *> getBuffer(BufferUsage usage);
gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
GLint startVertex);
gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(
SourceIndexData *indexInfo,
const TranslatedAttribute &attribute);
gl::ErrorOrResult<ID3D11Buffer *> getConstantBufferRange(GLintptr offset, GLsizeiptr size);
gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRV(DXGI_FORMAT srvFormat);
bool isMapped() const { return mMappedStorage != nullptr; }
......@@ -75,32 +74,18 @@ class Buffer11 : public BufferD3D
size_t getTotalCPUBufferMemoryBytes() const;
// BufferD3D implementation
size_t getSize() const override { return mSize; }
bool supportsDirectBinding() const override;
virtual size_t getSize() const { return mSize; }
virtual bool supportsDirectBinding() const;
gl::Error getData(const uint8_t **outData) override;
void initializeStaticData() override;
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 copySubData(BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size) override;
gl::Error map(GLenum access, GLvoid **mapPtr) override;
gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
gl::Error unmap(GLboolean *result) override;
gl::Error markTransformFeedbackUsage() override;
// We use two set of dirty callbacks for two events. Static buffers are marked dirty whenever
// the data is changed, because they must be re-translated. Direct buffers only need to be
// updated when the underlying ID3D11Buffer pointer changes - hopefully far less often.
void addStaticBufferDirtyCallback(const NotificationCallback *callback);
void removeStaticBufferDirtyCallback(const NotificationCallback *callback);
void addDirectBufferDirtyCallback(const NotificationCallback *callback);
void removeDirectBufferDirtyCallback(const NotificationCallback *callback);
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();
private:
class BufferStorage;
......@@ -109,6 +94,13 @@ class Buffer11 : public BufferD3D
class PackStorage;
class SystemMemoryStorage;
Renderer11 *mRenderer;
size_t mSize;
BufferStorage *mMappedStorage;
std::vector<BufferStorage*> mBufferStorages;
struct ConstantBufferCacheEntry
{
ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { }
......@@ -117,27 +109,6 @@ class Buffer11 : public BufferD3D
unsigned int lruCount;
};
gl::Error markBufferUsage();
gl::ErrorOrResult<NativeStorage *> getStagingStorage();
gl::ErrorOrResult<PackStorage *> getPackStorage();
gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage();
gl::Error updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
gl::ErrorOrResult<BufferStorage *> getBufferStorage(BufferUsage usage);
gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage() const;
gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(GLintptr offset,
GLsizeiptr size);
BufferStorage *allocateStorage(BufferUsage usage) const;
Renderer11 *mRenderer;
size_t mSize;
BufferStorage *mMappedStorage;
std::vector<BufferStorage *> mBufferStorages;
// Cache of D3D11 constant buffer for specific ranges of buffer data.
// This is used to emulate UBO ranges on 11.0 devices.
// Constant buffers are indexed by there start offset.
......@@ -151,8 +122,17 @@ class Buffer11 : public BufferD3D
unsigned int mReadUsageCount;
NotificationSet mStaticBufferDirtyCallbacks;
NotificationSet mDirectBufferDirtyCallbacks;
gl::Error markBufferUsage();
gl::ErrorOrResult<NativeStorage *> getStagingStorage();
gl::ErrorOrResult<PackStorage *> getPackStorage();
gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage();
gl::Error updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
gl::ErrorOrResult<BufferStorage *> getBufferStorage(BufferUsage usage);
gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage() const;
gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(GLintptr offset,
GLsizeiptr size);
};
} // namespace rx
......
......@@ -94,8 +94,7 @@ Optional<size_t> FindFirstNonInstanced(
}
void SortAttributesByLayout(const gl::Program *program,
const std::vector<TranslatedAttribute> &vertexArrayAttribs,
const std::vector<TranslatedAttribute> &currentValueAttribs,
const std::vector<TranslatedAttribute> &unsortedAttributes,
AttribIndexArray *sortedD3DSemanticsOut,
std::vector<const TranslatedAttribute *> *sortedAttributesOut)
{
......@@ -113,17 +112,7 @@ void SortAttributesByLayout(const gl::Program *program,
}
(*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
{
(*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
}
else
{
ASSERT(currentValueAttribs[locationIndex].attribute);
(*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
}
(*sortedAttributesOut)[d3dSemantic] = &unsortedAttributes[locationIndex];
}
}
......@@ -220,10 +209,8 @@ void InputLayoutCache::markDirty()
gl::Error InputLayoutCache::applyVertexBuffers(
const gl::State &state,
const std::vector<TranslatedAttribute> &vertexArrayAttribs,
const std::vector<TranslatedAttribute> &currentValueAttribs,
const std::vector<TranslatedAttribute> &unsortedAttributes,
GLenum mode,
GLint start,
TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance)
{
......@@ -236,7 +223,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
AttribIndexArray sortedSemanticIndices;
SortAttributesByLayout(program, vertexArrayAttribs, currentValueAttribs, &sortedSemanticIndices,
SortAttributesByLayout(program, unsortedAttributes, &sortedSemanticIndices,
&mCurrentAttributes);
// If we are using FL 9_3, make sure the first attribute is not instanced
......@@ -298,9 +285,9 @@ gl::Error InputLayoutCache::applyVertexBuffers(
indexInfo->srcIndexData.srcIndices = bufferData + offset;
}
ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData,
attrib, start),
buffer);
ANGLE_TRY_RESULT(
bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, attrib),
buffer);
}
else
{
......@@ -309,7 +296,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
}
vertexStride = attrib.stride;
ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset);
vertexOffset = attrib.offset;
}
size_t bufferIndex = reservedBuffers + attribIndex;
......@@ -427,8 +414,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
return gl::NoError();
}
gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
GLsizei emulatedInstanceId)
gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId)
{
size_t reservedBuffers = GetReservedBufferCount(true);
for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
......@@ -438,10 +424,8 @@ gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLint st
if (attrib.divisor > 0)
{
unsigned int offset = 0;
ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset);
mCurrentVertexOffsets[bufferIndex] =
offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
}
}
......
......@@ -46,15 +46,12 @@ class InputLayoutCache : angle::NonCopyable
void markDirty();
gl::Error applyVertexBuffers(const gl::State &state,
const std::vector<TranslatedAttribute> &vertexArrayAttribs,
const std::vector<TranslatedAttribute> &currentValueAttribs,
const std::vector<TranslatedAttribute> &attributes,
GLenum mode,
GLint start,
TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance);
gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
GLsizei emulatedInstanceId);
gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId);
// Useful for testing
void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; }
......
......@@ -189,17 +189,23 @@ RenderTarget11::~RenderTarget11()
void RenderTarget11::addDirtyCallback(const NotificationCallback *callback)
{
mDirtyCallbacks.add(callback);
mDirtyCallbacks.insert(callback);
}
void RenderTarget11::removeDirtyCallback(const NotificationCallback *callback)
{
mDirtyCallbacks.remove(callback);
mDirtyCallbacks.erase(callback);
}
void RenderTarget11::signalDirty()
{
mDirtyCallbacks.signal();
if (mDirtyCallbacks.empty())
return;
for (const auto &callback : mDirtyCallbacks)
{
(*callback)();
}
// Clear the signal list. We can't do this in the callback because it mutates the iterator.
mDirtyCallbacks.clear();
......
......@@ -41,7 +41,8 @@ class RenderTarget11 : public RenderTargetD3D
d3d11::ANGLEFormat getANGLEFormat() const { return mANGLEFormat; }
protected:
NotificationSet mDirtyCallbacks;
std::set<const NotificationCallback *> mDirtyCallbacks;
d3d11::ANGLEFormat mANGLEFormat;
};
......
......@@ -835,6 +835,9 @@ void Renderer11::initializeDevice()
ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel",
angleFeatureLevel,
NUM_ANGLE_FEATURE_LEVELS);
// TODO(jmadill): use context caps, and place in common D3D location
mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
}
void Renderer11::populateRenderer11DeviceCaps()
......@@ -1521,17 +1524,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
GLsizei instances,
TranslatedIndexData *indexInfo)
{
const auto &vertexArray = state.getVertexArray();
auto *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
gl::Error error = vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first,
count, instances);
if (error.isError())
{
return error;
}
error = mStateManager.updateCurrentValueAttribs(state, mVertexDataManager);
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
if (error.isError())
{
return error;
......@@ -1548,21 +1541,8 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
{
numIndicesPerInstance = count;
}
const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs();
const auto &currentValueAttribs = mStateManager.getCurrentValueAttribs();
ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs,
mode, first, indexInfo, numIndicesPerInstance));
// InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
// buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
// allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
// dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
// update on the second draw call.
// Hence we clear the flags here, after we've applied vertex data, since we know everything
// is clean. This is a bit of a hack.
vertexArray11->clearDirtyAndPromoteDynamicAttribs(state, count);
return gl::NoError();
return mInputLayoutCache.applyVertexBuffers(state, mTranslatedAttribCache, mode, indexInfo,
numIndicesPerInstance);
}
gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
......@@ -1689,7 +1669,6 @@ gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances)
{
......@@ -1782,8 +1761,7 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
// offsets.
for (GLsizei i = 0; i < instances; i++)
{
gl::Error error =
mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i);
gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
if (error.isError())
{
return error;
......@@ -1849,8 +1827,7 @@ gl::Error Renderer11::drawElementsImpl(const gl::Data &data,
// offsets.
for (GLsizei i = 0; i < instances; i++)
{
gl::Error error =
mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(minIndex, i);
gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
if (error.isError())
{
return error;
......@@ -2528,7 +2505,6 @@ void Renderer11::markAllStateDirty()
void Renderer11::releaseDeviceResources()
{
mStateManager.deinitialize();
mStateCache.clear();
mInputLayoutCache.clear();
......@@ -4364,5 +4340,4 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
*device = static_cast<DeviceImpl *>(mEGLDevice);
return egl::Error(EGL_SUCCESS);
}
} // namespace rx
}
......@@ -306,7 +306,6 @@ class Renderer11 : public RendererD3D
private:
gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances) override;
gl::Error drawElementsImpl(const gl::Data &data,
......
......@@ -150,9 +150,7 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurNear(0.0f),
mCurFar(0.0f),
mViewportBounds(),
mRenderTargetIsDirty(false),
mDirtyCurrentValueAttribs(),
mCurrentValueAttribs()
mRenderTargetIsDirty(false)
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
......@@ -193,9 +191,6 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurRasterState.polygonOffsetUnits = 0.0f;
mCurRasterState.pointDrawMode = false;
mCurRasterState.multiSample = false;
// Initially all current value attributes must be updated on first use.
mDirtyCurrentValueAttribs.flip();
}
StateManager11::~StateManager11()
......@@ -246,7 +241,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
return;
}
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
{
switch (dirtyBit)
{
......@@ -466,13 +461,6 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
mRenderTargetIsDirty = true;
break;
default:
if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX)
{
size_t attribIndex =
static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0);
mDirtyCurrentValueAttribs.set(attribIndex);
}
break;
}
}
......@@ -970,13 +958,6 @@ void StateManager11::initialize(const gl::Caps &caps)
// Initialize cached NULL SRV block
mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
mCurrentValueAttribs.resize(caps.maxVertexAttributes);
}
void StateManager11::deinitialize()
{
mCurrentValueAttribs.clear();
}
gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer)
......@@ -1097,40 +1078,4 @@ gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer)
return gl::Error(GL_NO_ERROR);
}
gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
VertexDataManager *vertexDataManager)
{
const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask();
const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs))
{
if (vertexAttributes[attribIndex].enabled)
continue;
mDirtyCurrentValueAttribs.reset(attribIndex);
const auto &currentValue =
state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
auto currentValueAttrib = &mCurrentValueAttribs[attribIndex];
currentValueAttrib->currentValueType = currentValue.Type;
currentValueAttrib->attribute = &vertexAttributes[attribIndex];
gl::Error error = vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib,
static_cast<size_t>(attribIndex));
if (error.isError())
{
return error;
}
}
return gl::Error(GL_NO_ERROR);
}
const std::vector<TranslatedAttribute> &StateManager11::getCurrentValueAttribs() const
{
return mCurrentValueAttribs;
}
} // namespace rx
......@@ -48,7 +48,6 @@ class StateManager11 final : angle::NonCopyable
~StateManager11();
void initialize(const gl::Caps &caps);
void deinitialize();
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
......@@ -92,11 +91,6 @@ class StateManager11 final : angle::NonCopyable
void onDeleteQueryObject(Query11 *query);
gl::Error onMakeCurrent(const gl::Data &data);
gl::Error updateCurrentValueAttribs(const gl::State &state,
VertexDataManager *vertexDataManager);
const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const;
private:
void setViewportBounds(const int width, const int height);
void unsetConflictingSRVs(gl::SamplerType shaderType,
......@@ -192,10 +186,6 @@ class StateManager11 final : angle::NonCopyable
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView *> mNullSRVs;
// Current translations of "Current-Value" data - owned by Context, not VertexArray.
gl::AttributesMask mDirtyCurrentValueAttribs;
std::vector<TranslatedAttribute> mCurrentValueAttribs;
};
} // namespace rx
......
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VertexArray11:
// Implementation of rx::VertexArray11.
//
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "common/BitSetIterator.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
namespace rx
{
namespace
{
size_t GetAttribIndex(unsigned long dirtyBit)
{
if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
{
return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
}
if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
{
return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
}
ASSERT(dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR);
return static_cast<size_t>(dirtyBit) - gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
}
} // anonymous namespace
VertexArray11::VertexArray11(const gl::VertexArray::Data &data)
: VertexArrayImpl(data),
mAttributeStorageTypes(data.getVertexAttributes().size(), VertexStorageType::CURRENT_VALUE),
mTranslatedAttribs(data.getVertexAttributes().size()),
mCurrentBuffers(data.getVertexAttributes().size())
{
for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex)
{
auto callback = [this, attribIndex]()
{
this->markBufferDataDirty(attribIndex);
};
mOnBufferDataDirty.push_back(callback);
}
}
VertexArray11::~VertexArray11()
{
for (auto &binding : mCurrentBuffers)
{
binding.set(nullptr);
}
}
void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits)
{
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
{
if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
continue;
size_t attribIndex = GetAttribIndex(dirtyBit);
mAttribsToUpdate.set(attribIndex);
}
}
void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
{
const auto &attrib = mData.getVertexAttribute(attribIndex);
// Note: having an unchanged storage type doesn't mean the attribute is clean.
auto oldStorageType = mAttributeStorageTypes[attribIndex];
auto newStorageType = ClassifyAttributeStorage(attrib);
mAttributeStorageTypes[attribIndex] = newStorageType;
if (newStorageType == VertexStorageType::DYNAMIC)
{
if (oldStorageType != VertexStorageType::DYNAMIC)
{
// Sync dynamic attribs in a different set.
mAttribsToTranslate.reset(attribIndex);
mDynamicAttribsMask.set(attribIndex);
}
}
else
{
mAttribsToTranslate.set(attribIndex);
if (oldStorageType == VertexStorageType::DYNAMIC)
{
ASSERT(mDynamicAttribsMask[attribIndex]);
mDynamicAttribsMask.reset(attribIndex);
}
}
gl::Buffer *oldBufferGL = mCurrentBuffers[attribIndex].get();
gl::Buffer *newBufferGL = attrib.buffer.get();
Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr;
Buffer11 *newBuffer11 = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr;
if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType)
{
// Note that for static callbacks, promotion to a static buffer from a dynamic buffer means
// we need to tag dynamic buffers with static callbacks.
if (oldBuffer11 != nullptr)
{
if (oldStorageType == VertexStorageType::DIRECT)
{
oldBuffer11->removeDirectBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
else if (oldStorageType == VertexStorageType::STATIC ||
oldStorageType == VertexStorageType::DYNAMIC)
{
oldBuffer11->removeStaticBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
}
if (newBuffer11 != nullptr)
{
if (newStorageType == VertexStorageType::DIRECT)
{
newBuffer11->addDirectBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
else if (newStorageType == VertexStorageType::STATIC ||
newStorageType == VertexStorageType::DYNAMIC)
{
newBuffer11->addStaticBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
}
mCurrentBuffers[attribIndex] = attrib.buffer;
}
}
gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
const gl::State &state,
GLint start,
GLsizei count,
GLsizei instances)
{
const gl::Program *program = state.getProgram();
const auto &activeLocations = program->getActiveAttribLocationsMask();
if (mAttribsToUpdate.any())
{
// Skip attrib locations the program doesn't use.
const auto &activeToUpdate = (mAttribsToUpdate & activeLocations);
for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate))
{
mAttribsToUpdate.reset(toUpdateIndex);
updateVertexAttribStorage(toUpdateIndex);
}
}
const auto &attribs = mData.getVertexAttributes();
if (mAttribsToTranslate.any())
{
// Skip attrib locations the program doesn't use, saving for the next frame.
const auto &dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
for (auto dirtyAttribIndex : angle::IterateBitSet(dirtyActiveAttribs))
{
mAttribsToTranslate.reset(dirtyAttribIndex);
auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
const auto &currentValue =
state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex));
// Record basic attrib info
translatedAttrib->attribute = &attribs[dirtyAttribIndex];
translatedAttrib->currentValueType = currentValue.Type;
translatedAttrib->divisor = translatedAttrib->attribute->divisor;
switch (mAttributeStorageTypes[dirtyAttribIndex])
{
case VertexStorageType::DIRECT:
VertexDataManager::StoreDirectAttrib(translatedAttrib);
break;
case VertexStorageType::STATIC:
{
auto error =
VertexDataManager::StoreStaticAttrib(translatedAttrib, count, instances);
if (error.isError())
{
return error;
}
break;
}
case VertexStorageType::CURRENT_VALUE:
// Current value attribs are managed by the StateManager11.
break;
default:
UNREACHABLE();
break;
}
}
}
if (mDynamicAttribsMask.any())
{
auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
for (auto dynamicAttribIndex : angle::IterateBitSet(activeDynamicAttribs))
{
auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
const auto &currentValue =
state.getVertexAttribCurrentValue(static_cast<unsigned int>(dynamicAttribIndex));
// Record basic attrib info
dynamicAttrib->attribute = &attribs[dynamicAttribIndex];
dynamicAttrib->currentValueType = currentValue.Type;
dynamicAttrib->divisor = dynamicAttrib->attribute->divisor;
}
return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs,
start, count, instances);
}
return gl::Error(GL_NO_ERROR);
}
const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
{
return mTranslatedAttribs;
}
void VertexArray11::markBufferDataDirty(size_t attribIndex)
{
ASSERT(mAttributeStorageTypes[attribIndex] != VertexStorageType::CURRENT_VALUE);
// This can change a buffer's storage, we'll need to re-check.
mAttribsToUpdate.set(attribIndex);
}
void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count)
{
const gl::Program *program = state.getProgram();
const auto &activeLocations = program->getActiveAttribLocationsMask();
mAttribsToUpdate &= ~activeLocations;
// Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness.
auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count);
}
} // namespace rx
......@@ -19,41 +19,13 @@ class Renderer11;
class VertexArray11 : public VertexArrayImpl
{
public:
VertexArray11(const gl::VertexArray::Data &data);
~VertexArray11() override;
void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
const gl::State &state,
GLint start,
GLsizei count,
GLsizei instances);
void clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count);
const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
private:
void updateVertexAttribStorage(size_t attribIndex);
void markBufferDataDirty(size_t attribIndex);
std::vector<VertexStorageType> mAttributeStorageTypes;
std::vector<TranslatedAttribute> mTranslatedAttribs;
// The mask of attributes marked as dynamic.
gl::AttributesMask mDynamicAttribsMask;
// A mask of attributes that need to be re-evaluated.
gl::AttributesMask mAttribsToUpdate;
// A set of attributes we know are dirty, and need to be re-translated.
gl::AttributesMask mAttribsToTranslate;
// We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers;
std::vector<NotificationCallback> mOnBufferDataDirty;
VertexArray11(const gl::VertexArray::Data &data)
: VertexArrayImpl(data)
{
}
virtual ~VertexArray11() {}
};
} // namespace rx
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
......@@ -1716,40 +1716,4 @@ bool UsePresentPathFast(const Renderer11 *renderer,
renderer->presentPathFastEnabled());
}
NotificationSet::NotificationSet()
{
}
NotificationSet::~NotificationSet()
{
}
void NotificationSet::add(const NotificationCallback *callback)
{
ASSERT(mCallbacks.count(callback) == 0);
mCallbacks.insert(callback);
}
void NotificationSet::remove(const NotificationCallback *callback)
{
ASSERT(mCallbacks.count(callback) == 1);
mCallbacks.erase(callback);
}
void NotificationSet::signal() const
{
if (mCallbacks.empty())
return;
for (const auto *callback : mCallbacks)
{
(*callback)();
}
}
void NotificationSet::clear()
{
mCallbacks.clear();
}
} // namespace rx
......@@ -406,21 +406,6 @@ bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachm
using NotificationCallback = std::function<void()>;
class NotificationSet final : angle::NonCopyable
{
public:
NotificationSet();
~NotificationSet();
void add(const NotificationCallback *callback);
void remove(const NotificationCallback *callback);
void signal() const;
void clear();
private:
std::set<const NotificationCallback *> mCallbacks;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
......@@ -154,8 +154,6 @@ void Renderer9::release()
{
RendererD3D::cleanup();
mTranslatedAttribCache.clear();
releaseDeviceResources();
SafeDelete(mEGLDevice);
......@@ -366,6 +364,7 @@ void Renderer9::initializeDevice()
mVertexDataManager = new VertexDataManager(this);
mIndexDataManager = new IndexDataManager(this, getRendererClass());
// TODO(jmadill): use context caps, and place in common D3D location
mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
}
......@@ -1192,8 +1191,7 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state,
return error;
}
return mVertexDeclarationCache.applyDeclaration(
mDevice, mTranslatedAttribCache, state.getProgram(), first, instances, &mRepeatDraw);
return mVertexDeclarationCache.applyDeclaration(mDevice, mTranslatedAttribCache, state.getProgram(), instances, &mRepeatDraw);
}
// Applies the indices and element array bindings to the Direct3D 9 device
......@@ -1235,7 +1233,6 @@ gl::Error Renderer9::applyTransformFeedbackBuffers(const gl::State &state)
gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances)
{
......
......@@ -275,7 +275,6 @@ class Renderer9 : public RendererD3D
private:
gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances) override;
gl::Error drawElementsImpl(const gl::Data &data,
......@@ -397,7 +396,6 @@ class Renderer9 : public RendererD3D
UINT mMaxNullColorbufferLRU;
DeviceD3D *mEGLDevice;
std::vector<TranslatedAttribute> mTranslatedAttribCache;
};
}
......
......@@ -42,13 +42,11 @@ VertexDeclarationCache::~VertexDeclarationCache()
}
}
gl::Error VertexDeclarationCache::applyDeclaration(
IDirect3DDevice9 *device,
const std::vector<TranslatedAttribute> &attributes,
gl::Program *program,
GLint start,
GLsizei instances,
GLsizei *repeatDraw)
gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
const std::vector<TranslatedAttribute> &attributes,
gl::Program *program,
GLsizei instances,
GLsizei *repeatDraw)
{
ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size());
......@@ -151,18 +149,14 @@ gl::Error VertexDeclarationCache::applyDeclaration(
VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer.get());
unsigned int offset = 0;
ANGLE_TRY_RESULT(attributes[i].computeOffset(start), offset);
if (mAppliedVBs[stream].serial != attributes[i].serial ||
mAppliedVBs[stream].stride != attributes[i].stride ||
mAppliedVBs[stream].offset != offset)
mAppliedVBs[stream].offset != attributes[i].offset)
{
device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset,
attributes[i].stride);
device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
mAppliedVBs[stream].serial = attributes[i].serial;
mAppliedVBs[stream].stride = attributes[i].stride;
mAppliedVBs[stream].offset = offset;
mAppliedVBs[stream].offset = attributes[i].offset;
}
gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT);
......
......@@ -30,7 +30,6 @@ class VertexDeclarationCache
gl::Error applyDeclaration(IDirect3DDevice9 *device,
const std::vector<TranslatedAttribute> &attributes,
gl::Program *program,
GLint start,
GLsizei instances,
GLsizei *repeatDraw);
......
......@@ -392,7 +392,6 @@
'libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp',
'libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.h',
'libANGLE/renderer/d3d/d3d11/texture_format_table.h',
'libANGLE/renderer/d3d/d3d11/VertexArray11.cpp',
'libANGLE/renderer/d3d/d3d11/VertexArray11.h',
'libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp',
'libANGLE/renderer/d3d/d3d11/VertexBuffer11.h',
......
......@@ -207,31 +207,6 @@ TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash)
delete[] data;
}
// Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
// path.
TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
{
std::vector<GLfloat> data;
for (int i = 0; i < 16; ++i)
{
data.push_back(static_cast<GLfloat>(i));
}
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(mAttribLocation);
for (int drawCount = 0; drawCount < 40; ++drawCount)
{
drawQuad(mProgram, "position", 0.5f);
}
EXPECT_GL_NO_ERROR();
}
class IndexedBufferCopyTest : public ANGLETest
{
protected:
......
......@@ -38,8 +38,7 @@ class D3D11EmulatedIndexedBufferTest : public ANGLETest
gl::Error error = mSourceBuffer->setData(testData, sizeof(testData), GL_STATIC_DRAW);
ASSERT_FALSE(error.isError());
mTranslatedAttribute.baseOffset = 0;
mTranslatedAttribute.usesFirstVertexOffset = false;
mTranslatedAttribute.offset = 0;
mTranslatedAttribute.stride = sizeof(GLfloat);
GLubyte indices[] = {0, 0, 3, 4, 2, 1, 1};
......@@ -108,8 +107,7 @@ class D3D11EmulatedIndexedBufferTest : public ANGLETest
void emulateAndCompare(rx::SourceIndexData *srcData)
{
auto bufferOrError =
mSourceBuffer->getEmulatedIndexedBuffer(srcData, mTranslatedAttribute, 0);
auto bufferOrError = mSourceBuffer->getEmulatedIndexedBuffer(srcData, mTranslatedAttribute);
ASSERT_FALSE(bufferOrError.isError());
ID3D11Buffer *emulatedBuffer = bufferOrError.getResult();
ASSERT_TRUE(emulatedBuffer != nullptr);
......
......@@ -50,8 +50,7 @@ GLfloat Normalize(T value)
class VertexAttributeTest : public ANGLETest
{
protected:
VertexAttributeTest()
: mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0), mQuadBuffer(0)
VertexAttributeTest() : mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0)
{
setWindowWidth(128);
setWindowHeight(128);
......@@ -123,23 +122,6 @@ class VertexAttributeTest : public ANGLETest
glEnableVertexAttribArray(mExpectedAttrib);
}
void checkPixels()
{
GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize);
GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
// We need to offset our checks from triangle edges to ensure we don't fall on a single tri
// Avoid making assumptions of drawQuad with four checks to check the four possible tri
// regions
EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
}
void runTest(const TestData &test)
{
// TODO(geofflang): Figure out why this is broken on AMD OpenGL
......@@ -149,6 +131,17 @@ class VertexAttributeTest : public ANGLETest
return;
}
if (mProgram == 0)
{
initBasicProgram();
}
GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize);
GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
for (GLint i = 0; i < 4; i++)
{
GLint typeSize = i + 1;
......@@ -159,7 +152,12 @@ class VertexAttributeTest : public ANGLETest
glDisableVertexAttribArray(mTestAttrib);
glDisableVertexAttribArray(mExpectedAttrib);
checkPixels();
// We need to offset our checks from triangle edges to ensure we don't fall on a single tri
// Avoid making assumptions of drawQuad with four checks to check the four possible tri regions
EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
}
}
......@@ -180,7 +178,6 @@ class VertexAttributeTest : public ANGLETest
{
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mBuffer);
glDeleteBuffers(1, &mQuadBuffer);
ANGLETest::TearDown();
}
......@@ -265,7 +262,6 @@ class VertexAttributeTest : public ANGLETest
GLint mTestAttrib;
GLint mExpectedAttrib;
GLuint mBuffer;
GLuint mQuadBuffer;
};
TEST_P(VertexAttributeTest, UnsignedByteUnnormalized)
......@@ -549,69 +545,6 @@ TEST_P(VertexAttributeTest, DrawElementsBufferTooSmall)
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
// Verify that using a different start vertex doesn't mess up the draw.
TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
{
// TODO(jmadill): Diagnose this failure.
if (IsD3D11_FL93())
{
std::cout << "Test disabled on D3D11 FL 9_3" << std::endl;
return;
}
// TODO(geofflang): Figure out why this is broken on AMD OpenGL
if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
{
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
initBasicProgram();
glUseProgram(mProgram);
GLfloat inputData[mVertexCount];
GLfloat expectedData[mVertexCount];
for (size_t count = 0; count < mVertexCount; ++count)
{
inputData[count] = static_cast<GLfloat>(count);
expectedData[count] = inputData[count];
}
auto quadVertices = GetQuadVertices();
GLsizei quadVerticesSize = static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
glGenBuffers(1, &mQuadBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
glBufferData(GL_ARRAY_BUFFER, quadVerticesSize + sizeof(Vector3), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
GLint positionLocation = glGetAttribLocation(mProgram, "position");
ASSERT_NE(-1, positionLocation);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation);
GLsizei dataSize = mVertexCount * TypeStride(GL_FLOAT);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, dataSize + TypeStride(GL_FLOAT), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, inputData);
glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(mTestAttrib);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData);
glEnableVertexAttribArray(mExpectedAttrib);
// Vertex draw with no start vertex offset (second argument is zero).
glDrawArrays(GL_TRIANGLES, 0, 6);
checkPixels();
// Draw offset by one vertex.
glDrawArrays(GL_TRIANGLES, 1, 6);
checkPixels();
EXPECT_GL_NO_ERROR();
}
class VertexAttributeCachingTest : public VertexAttributeTest
{
protected:
......
......@@ -154,19 +154,6 @@ void ANGLETest::swapBuffers()
}
}
// static
std::array<Vector3, 6> ANGLETest::GetQuadVertices()
{
std::array<Vector3, 6> vertices;
vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
vertices[3] = Vector3(-1.0f, 1.0f, 0.5f);
vertices[4] = Vector3(1.0f, -1.0f, 0.5f);
vertices[5] = Vector3(1.0f, 1.0f, 0.5f);
return vertices;
}
void ANGLETest::drawQuad(GLuint program,
const std::string &positionAttribName,
GLfloat positionAttribZ)
......@@ -188,15 +175,17 @@ void ANGLETest::drawQuad(GLuint program,
GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
auto quadVertices = GetQuadVertices();
for (Vector3 &vertex : quadVertices)
{
vertex.x *= positionAttribXYScale;
vertex.y *= positionAttribXYScale;
vertex.z = positionAttribZ;
}
const GLfloat vertices[] = {
-1.0f * positionAttribXYScale, 1.0f * positionAttribXYScale, positionAttribZ,
-1.0f * positionAttribXYScale, -1.0f * positionAttribXYScale, positionAttribZ,
1.0f * positionAttribXYScale, -1.0f * positionAttribXYScale, positionAttribZ,
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
-1.0f * positionAttribXYScale, 1.0f * positionAttribXYScale, positionAttribZ,
1.0f * positionAttribXYScale, -1.0f * positionAttribXYScale, positionAttribZ,
1.0f * positionAttribXYScale, 1.0f * positionAttribXYScale, positionAttribZ,
};
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 6);
......@@ -232,15 +221,14 @@ void ANGLETest::drawIndexedQuad(GLuint program,
if (mQuadVertexBuffer == 0)
{
glGenBuffers(1, &mQuadVertexBuffer);
auto quadVertices = GetQuadVertices();
for (Vector3 &vertex : quadVertices)
{
vertex.x *= positionAttribXYScale;
vertex.y *= positionAttribXYScale;
vertex.z = positionAttribZ;
}
const GLfloat vertices[] = {
-1.0f * positionAttribXYScale, 1.0f * positionAttribXYScale, positionAttribZ,
-1.0f * positionAttribXYScale, -1.0f * positionAttribXYScale, positionAttribZ,
1.0f * positionAttribXYScale, -1.0f * positionAttribXYScale, positionAttribZ,
1.0f * positionAttribXYScale, 1.0f * positionAttribXYScale, positionAttribZ,
};
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, vertices, GL_STATIC_DRAW);
}
else
{
......
......@@ -12,7 +12,6 @@
#include <gtest/gtest.h>
#include <algorithm>
#include <array>
#include "angle_gl.h"
#include "angle_test_configs.h"
......@@ -115,7 +114,6 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
const std::string &positionAttribName,
GLfloat positionAttribZ,
GLfloat positionAttribXYScale);
static std::array<Vector3, 6> GetQuadVertices();
void drawIndexedQuad(GLuint program,
const std::string &positionAttribName,
GLfloat positionAttribZ);
......
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