Commit 00f394ec by Corentin Wallez

Revert Dirty bits for VertexArray11

This is a combination of two reverts: Revert "D3D11: Remove unused mRenderer from VertexArray11." Revert "D3D11: Implement dirty bits for VertexArray11." Reverting only the first commit would trigger warnings on the Windows clang bot. BUG=594509 BUG=angleproject:1327 This reverts commit fc4712b5. This reverts commit 7d8585b8. Change-Id: I612dbba0816d6144f71ce815701c13a798585bc7 Reviewed-on: https://chromium-review.googlesource.com/332989Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent a0fc18d9
...@@ -29,7 +29,9 @@ VertexArray::Data::~Data() ...@@ -29,7 +29,9 @@ VertexArray::Data::~Data()
} }
VertexArray::VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs) 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 ...@@ -114,10 +114,10 @@ class VertexArray final : public LabeledObject
private: private:
GLuint mId; GLuint mId;
rx::VertexArrayImpl *mVertexArray;
Data mData; Data mData;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
rx::VertexArrayImpl *mVertexArray;
}; };
} }
......
...@@ -161,13 +161,13 @@ void BufferD3D::invalidateStaticData() ...@@ -161,13 +161,13 @@ void BufferD3D::invalidateStaticData()
// Creates static buffers if sufficient used data has been left unmodified // Creates static buffers if sufficient used data has been left unmodified
void BufferD3D::promoteStaticUsage(int dataSize) void BufferD3D::promoteStaticUsage(int dataSize)
{ {
if (mUsage == D3DBufferUsage::DYNAMIC) if (mStaticVertexBuffers.empty() && !mStaticIndexBuffer)
{ {
mUnmodifiedDataUse += dataSize; mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * getSize()) if (mUnmodifiedDataUse > 3 * getSize())
{ {
updateD3DBufferUsage(GL_STATIC_DRAW); initializeStaticData();
} }
} }
} }
......
...@@ -43,8 +43,8 @@ class BufferD3D : public BufferImpl ...@@ -43,8 +43,8 @@ class BufferD3D : public BufferImpl
StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute); StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute);
StaticIndexBufferInterface *getStaticIndexBuffer(); StaticIndexBufferInterface *getStaticIndexBuffer();
virtual void initializeStaticData(); void initializeStaticData();
virtual void invalidateStaticData(); void invalidateStaticData();
void promoteStaticUsage(int dataSize); void promoteStaticUsage(int dataSize);
......
...@@ -55,6 +55,7 @@ RendererD3D::~RendererD3D() ...@@ -55,6 +55,7 @@ RendererD3D::~RendererD3D()
void RendererD3D::cleanup() void RendererD3D::cleanup()
{ {
mTranslatedAttribCache.clear();
mScratchMemoryBuffer.resize(0); mScratchMemoryBuffer.resize(0);
for (auto &incompleteTexture : mIncompleteTextures) for (auto &incompleteTexture : mIncompleteTextures)
{ {
......
...@@ -282,6 +282,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -282,6 +282,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
void initializeDebugAnnotator(); void initializeDebugAnnotator();
gl::DebugAnnotator *mAnnotator; gl::DebugAnnotator *mAnnotator;
std::vector<TranslatedAttribute> mTranslatedAttribCache;
bool mPresentPathFastEnabled; bool mPresentPathFastEnabled;
private: private:
......
...@@ -80,7 +80,7 @@ class VertexBufferInterface : angle::NonCopyable ...@@ -80,7 +80,7 @@ class VertexBufferInterface : angle::NonCopyable
unsigned int getSerial() const; unsigned int getSerial() const;
VertexBuffer *getVertexBuffer() const; VertexBuffer* getVertexBuffer() const;
protected: protected:
gl::Error discard(); gl::Error discard();
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "common/BitSetIterator.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
...@@ -202,7 +201,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, ...@@ -202,7 +201,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
const gl::VertexArray *vertexArray = state.getVertexArray(); const gl::VertexArray *vertexArray = state.getVertexArray();
const auto &vertexAttributes = vertexArray->getVertexAttributes(); const auto &vertexAttributes = vertexArray->getVertexAttributes();
mDynamicAttribsMaskCache.reset(); mDynamicAttributeIndexesCache.clear();
const gl::Program *program = state.getProgram(); const gl::Program *program = state.getProgram();
translatedAttribs->clear(); translatedAttribs->clear();
...@@ -242,7 +241,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, ...@@ -242,7 +241,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
} }
case VertexStorageType::DYNAMIC: case VertexStorageType::DYNAMIC:
// Dynamic attributes must be handled together. // Dynamic attributes must be handled together.
mDynamicAttribsMaskCache.set(attribIndex); mDynamicAttributeIndexesCache.push_back(attribIndex);
break; break;
case VertexStorageType::DIRECT: case VertexStorageType::DIRECT:
// Update translated data for direct attributes. // Update translated data for direct attributes.
...@@ -263,12 +262,12 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, ...@@ -263,12 +262,12 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
} }
} }
if (mDynamicAttribsMaskCache.none()) if (mDynamicAttributeIndexesCache.empty())
{ {
gl::Error(GL_NO_ERROR); gl::Error(GL_NO_ERROR);
} }
return storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, return storeDynamicAttribs(translatedAttribs, mDynamicAttributeIndexesCache, start, count,
instances); instances);
} }
...@@ -366,13 +365,13 @@ gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated, ...@@ -366,13 +365,13 @@ gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated,
gl::Error VertexDataManager::storeDynamicAttribs( gl::Error VertexDataManager::storeDynamicAttribs(
std::vector<TranslatedAttribute> *translatedAttribs, std::vector<TranslatedAttribute> *translatedAttribs,
const gl::AttributesMask &dynamicAttribsMask, const std::vector<size_t> &dynamicAttribIndexes,
GLint start, GLint start,
GLsizei count, GLsizei count,
GLsizei instances) GLsizei instances)
{ {
// Reserve the required space for the dynamic buffers. // Reserve the required space for the dynamic buffers.
for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask)) for (size_t attribIndex : dynamicAttribIndexes)
{ {
const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
gl::Error error = reserveSpaceForAttrib(dynamicAttrib, count, instances); gl::Error error = reserveSpaceForAttrib(dynamicAttrib, count, instances);
...@@ -383,7 +382,7 @@ gl::Error VertexDataManager::storeDynamicAttribs( ...@@ -383,7 +382,7 @@ gl::Error VertexDataManager::storeDynamicAttribs(
} }
// Store dynamic attributes // Store dynamic attributes
for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask)) for (size_t attribIndex : dynamicAttribIndexes)
{ {
auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
gl::Error error = storeDynamicAttrib(dynamicAttrib, start, count, instances); gl::Error error = storeDynamicAttrib(dynamicAttrib, start, count, instances);
...@@ -392,14 +391,8 @@ gl::Error VertexDataManager::storeDynamicAttribs( ...@@ -392,14 +391,8 @@ gl::Error VertexDataManager::storeDynamicAttribs(
unmapStreamingBuffer(); unmapStreamingBuffer();
return error; return error;
} }
}
unmapStreamingBuffer();
// Promote static usage of dynamic buffers. // Promote static usage of dynamic buffers.
for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask))
{
auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
gl::Buffer *buffer = dynamicAttrib->attribute->buffer.get(); gl::Buffer *buffer = dynamicAttrib->attribute->buffer.get();
if (buffer) if (buffer)
{ {
...@@ -409,6 +402,7 @@ gl::Error VertexDataManager::storeDynamicAttribs( ...@@ -409,6 +402,7 @@ gl::Error VertexDataManager::storeDynamicAttribs(
} }
} }
unmapStreamingBuffer();
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -10,10 +10,9 @@ ...@@ -10,10 +10,9 @@
#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ #ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
#define 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/Constants.h"
#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexAttribute.h"
#include "common/angleutils.h"
namespace gl namespace gl
{ {
...@@ -93,7 +92,7 @@ class VertexDataManager : angle::NonCopyable ...@@ -93,7 +92,7 @@ class VertexDataManager : angle::NonCopyable
GLsizei instances); GLsizei instances);
gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs, gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs,
const gl::AttributesMask &dynamicAttribsMask, const std::vector<size_t> &dynamicAttribIndexes,
GLint start, GLint start,
GLsizei count, GLsizei count,
GLsizei instances); GLsizei instances);
...@@ -128,7 +127,7 @@ class VertexDataManager : angle::NonCopyable ...@@ -128,7 +127,7 @@ class VertexDataManager : angle::NonCopyable
StreamingVertexBufferInterface *mStreamingBuffer; StreamingVertexBufferInterface *mStreamingBuffer;
std::vector<CurrentValueState> mCurrentValueCache; std::vector<CurrentValueState> mCurrentValueCache;
gl::AttributesMask mDynamicAttribsMaskCache; std::vector<size_t> mDynamicAttributeIndexesCache;
}; };
} // namespace rx } // namespace rx
......
...@@ -127,7 +127,7 @@ class Buffer11::BufferStorage : angle::NonCopyable ...@@ -127,7 +127,7 @@ class Buffer11::BufferStorage : angle::NonCopyable
class Buffer11::NativeStorage : public Buffer11::BufferStorage class Buffer11::NativeStorage : public Buffer11::BufferStorage
{ {
public: public:
NativeStorage(Renderer11 *renderer, BufferUsage usage, const NotificationSet *onStorageChanged); NativeStorage(Renderer11 *renderer, BufferUsage usage);
~NativeStorage() override; ~NativeStorage() override;
bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
...@@ -149,7 +149,6 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage ...@@ -149,7 +149,6 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
unsigned int bufferSize); unsigned int bufferSize);
ID3D11Buffer *mNativeStorage; ID3D11Buffer *mNativeStorage;
const NotificationSet *mOnStorageChanged;
}; };
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data // A emulated indexed buffer storage represents an underlying D3D11 buffer for data
...@@ -665,7 +664,23 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) ...@@ -665,7 +664,23 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage)
if (!newStorage) 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 // resize buffer
...@@ -683,23 +698,6 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) ...@@ -683,23 +698,6 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage)
return newStorage; 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);
}
}
Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size) Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size)
{ {
BufferStorage *newStorage; BufferStorage *newStorage;
...@@ -711,7 +709,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset ...@@ -711,7 +709,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
if (!cacheEntry->storage) if (!cacheEntry->storage)
{ {
cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM); cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM);
cacheEntry->lruCount = ++mMaxConstantBufferLruCount; cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
} }
...@@ -850,43 +848,8 @@ bool Buffer11::supportsDirectBinding() const ...@@ -850,43 +848,8 @@ bool Buffer11::supportsDirectBinding() const
{ {
// Do not support direct buffers for dynamic data. The streaming buffer // Do not support direct buffers for dynamic data. The streaming buffer
// offers better performance for data which changes every frame. // offers better performance for data which changes every frame.
return (mUsage == D3DBufferUsage::STATIC); // Check for absence of static buffer interfaces to detect dynamic data.
} return (!mStaticVertexBuffers.empty() && mStaticIndexBuffer);
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);
} }
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
...@@ -911,10 +874,8 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s ...@@ -911,10 +874,8 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage)
BufferUsage usage, : BufferStorage(renderer, usage), mNativeStorage(nullptr)
const NotificationSet *onStorageChanged)
: BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged)
{ {
} }
...@@ -1026,12 +987,6 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) ...@@ -1026,12 +987,6 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
mBufferSize = bufferDesc.ByteWidth; mBufferSize = bufferDesc.ByteWidth;
// Notify that the storage has changed.
if (mOnStorageChanged)
{
mOnStorageChanged->signal();
}
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -1471,4 +1426,4 @@ void Buffer11::SystemMemoryStorage::unmap() ...@@ -1471,4 +1426,4 @@ void Buffer11::SystemMemoryStorage::unmap()
{ {
// No-op // No-op
} }
} // namespace rx }
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl namespace gl
{ {
...@@ -67,38 +66,24 @@ class Buffer11 : public BufferD3D ...@@ -67,38 +66,24 @@ class Buffer11 : public BufferD3D
ID3D11Buffer *getEmulatedIndexedBuffer(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); ID3D11Buffer *getEmulatedIndexedBuffer(SourceIndexData *indexInfo, const TranslatedAttribute *attribute);
ID3D11Buffer *getConstantBufferRange(GLintptr offset, GLsizeiptr size); ID3D11Buffer *getConstantBufferRange(GLintptr offset, GLsizeiptr size);
ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat);
bool isMapped() const { return mMappedStorage != nullptr; } bool isMapped() const { return mMappedStorage != NULL; }
gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params); const PackPixelsParams &params);
size_t getTotalCPUBufferMemoryBytes() const; size_t getTotalCPUBufferMemoryBytes() const;
// BufferD3D implementation // BufferD3D implementation
size_t getSize() const override { return mSize; } virtual size_t getSize() const { return mSize; }
bool supportsDirectBinding() const override; virtual bool supportsDirectBinding() const;
gl::Error getData(const uint8_t **outData) override; gl::Error getData(const uint8_t **outData) override;
void initializeStaticData() override;
void invalidateStaticData() override;
// BufferImpl implementation // BufferImpl implementation
gl::Error setData(const void *data, size_t size, GLenum usage) override; virtual gl::Error setData(const void* data, size_t size, GLenum usage);
gl::Error setSubData(const void *data, size_t size, size_t offset) override; virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
gl::Error copySubData(BufferImpl *source, virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
GLintptr sourceOffset, virtual gl::Error map(GLenum access, GLvoid **mapPtr);
GLintptr destOffset, virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
GLsizeiptr size) override; virtual gl::Error unmap(GLboolean *result);
gl::Error map(GLenum access, GLvoid **mapPtr) override; virtual void markTransformFeedbackUsage();
gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
gl::Error unmap(GLboolean *result) override;
void 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);
private: private:
class BufferStorage; class BufferStorage;
...@@ -107,6 +92,13 @@ class Buffer11 : public BufferD3D ...@@ -107,6 +92,13 @@ class Buffer11 : public BufferD3D
class PackStorage; class PackStorage;
class SystemMemoryStorage; class SystemMemoryStorage;
Renderer11 *mRenderer;
size_t mSize;
BufferStorage *mMappedStorage;
std::vector<BufferStorage*> mBufferStorages;
struct ConstantBufferCacheEntry struct ConstantBufferCacheEntry
{ {
ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { } ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { }
...@@ -115,26 +107,6 @@ class Buffer11 : public BufferD3D ...@@ -115,26 +107,6 @@ class Buffer11 : public BufferD3D
unsigned int lruCount; unsigned int lruCount;
}; };
void markBufferUsage();
NativeStorage *getStagingStorage();
PackStorage *getPackStorage();
gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut);
void updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
BufferStorage *getBufferStorage(BufferUsage usage);
BufferStorage *getLatestBufferStorage() const;
BufferStorage *getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size);
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. // Cache of D3D11 constant buffer for specific ranges of buffer data.
// This is used to emulate UBO ranges on 11.0 devices. // This is used to emulate UBO ranges on 11.0 devices.
// Constant buffers are indexed by there start offset. // Constant buffers are indexed by there start offset.
...@@ -148,10 +120,20 @@ class Buffer11 : public BufferD3D ...@@ -148,10 +120,20 @@ class Buffer11 : public BufferD3D
unsigned int mReadUsageCount; unsigned int mReadUsageCount;
NotificationSet mStaticBufferDirtyCallbacks; void markBufferUsage();
NotificationSet mDirectBufferDirtyCallbacks; NativeStorage *getStagingStorage();
PackStorage *getPackStorage();
gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut);
void updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
BufferStorage *getBufferStorage(BufferUsage usage);
BufferStorage *getLatestBufferStorage() const;
BufferStorage *getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size);
void invalidateEmulatedIndexedBuffer();
}; };
} // namespace rx }
#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
...@@ -94,8 +94,7 @@ Optional<size_t> FindFirstNonInstanced( ...@@ -94,8 +94,7 @@ Optional<size_t> FindFirstNonInstanced(
} }
void SortAttributesByLayout(const gl::Program *program, void SortAttributesByLayout(const gl::Program *program,
const std::vector<TranslatedAttribute> &vertexArrayAttribs, const std::vector<TranslatedAttribute> &unsortedAttributes,
const std::vector<TranslatedAttribute> &currentValueAttribs,
AttribIndexArray *sortedD3DSemanticsOut, AttribIndexArray *sortedD3DSemanticsOut,
std::vector<const TranslatedAttribute *> *sortedAttributesOut) std::vector<const TranslatedAttribute *> *sortedAttributesOut)
{ {
...@@ -113,17 +112,7 @@ void SortAttributesByLayout(const gl::Program *program, ...@@ -113,17 +112,7 @@ void SortAttributesByLayout(const gl::Program *program,
} }
(*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic; (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
(*sortedAttributesOut)[d3dSemantic] = &unsortedAttributes[locationIndex];
const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
{
(*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
}
else
{
ASSERT(currentValueAttribs[locationIndex].attribute);
(*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
}
} }
} }
...@@ -220,8 +209,7 @@ void InputLayoutCache::markDirty() ...@@ -220,8 +209,7 @@ void InputLayoutCache::markDirty()
gl::Error InputLayoutCache::applyVertexBuffers( gl::Error InputLayoutCache::applyVertexBuffers(
const gl::State &state, const gl::State &state,
const std::vector<TranslatedAttribute> &vertexArrayAttribs, const std::vector<TranslatedAttribute> &unsortedAttributes,
const std::vector<TranslatedAttribute> &currentValueAttribs,
GLenum mode, GLenum mode,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance) GLsizei numIndicesPerInstance)
...@@ -235,7 +223,7 @@ gl::Error InputLayoutCache::applyVertexBuffers( ...@@ -235,7 +223,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
AttribIndexArray sortedSemanticIndices; AttribIndexArray sortedSemanticIndices;
SortAttributesByLayout(program, vertexArrayAttribs, currentValueAttribs, &sortedSemanticIndices, SortAttributesByLayout(program, unsortedAttributes, &sortedSemanticIndices,
&mCurrentAttributes); &mCurrentAttributes);
// If we are using FL 9_3, make sure the first attribute is not instanced // If we are using FL 9_3, make sure the first attribute is not instanced
......
...@@ -46,8 +46,7 @@ class InputLayoutCache : angle::NonCopyable ...@@ -46,8 +46,7 @@ class InputLayoutCache : angle::NonCopyable
void markDirty(); void markDirty();
gl::Error applyVertexBuffers(const gl::State &state, gl::Error applyVertexBuffers(const gl::State &state,
const std::vector<TranslatedAttribute> &vertexArrayAttribs, const std::vector<TranslatedAttribute> &attributes,
const std::vector<TranslatedAttribute> &currentValueAttribs,
GLenum mode, GLenum mode,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance); GLsizei numIndicesPerInstance);
......
...@@ -189,17 +189,23 @@ RenderTarget11::~RenderTarget11() ...@@ -189,17 +189,23 @@ RenderTarget11::~RenderTarget11()
void RenderTarget11::addDirtyCallback(const NotificationCallback *callback) void RenderTarget11::addDirtyCallback(const NotificationCallback *callback)
{ {
mDirtyCallbacks.add(callback); mDirtyCallbacks.insert(callback);
} }
void RenderTarget11::removeDirtyCallback(const NotificationCallback *callback) void RenderTarget11::removeDirtyCallback(const NotificationCallback *callback)
{ {
mDirtyCallbacks.remove(callback); mDirtyCallbacks.erase(callback);
} }
void RenderTarget11::signalDirty() 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. // Clear the signal list. We can't do this in the callback because it mutates the iterator.
mDirtyCallbacks.clear(); mDirtyCallbacks.clear();
......
...@@ -41,7 +41,8 @@ class RenderTarget11 : public RenderTargetD3D ...@@ -41,7 +41,8 @@ class RenderTarget11 : public RenderTargetD3D
d3d11::ANGLEFormat getANGLEFormat() const { return mANGLEFormat; } d3d11::ANGLEFormat getANGLEFormat() const { return mANGLEFormat; }
protected: protected:
NotificationSet mDirtyCallbacks; std::set<const NotificationCallback *> mDirtyCallbacks;
d3d11::ANGLEFormat mANGLEFormat; d3d11::ANGLEFormat mANGLEFormat;
}; };
......
...@@ -833,6 +833,9 @@ void Renderer11::initializeDevice() ...@@ -833,6 +833,9 @@ void Renderer11::initializeDevice()
ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel",
angleFeatureLevel, angleFeatureLevel,
NUM_ANGLE_FEATURE_LEVELS); NUM_ANGLE_FEATURE_LEVELS);
// TODO(jmadill): use context caps, and place in common D3D location
mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
} }
void Renderer11::populateRenderer11DeviceCaps() void Renderer11::populateRenderer11DeviceCaps()
...@@ -1495,17 +1498,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, ...@@ -1495,17 +1498,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
GLsizei instances, GLsizei instances,
TranslatedIndexData *indexInfo) TranslatedIndexData *indexInfo)
{ {
const auto &vertexArray = state.getVertexArray(); gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
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);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -1522,10 +1515,8 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, ...@@ -1522,10 +1515,8 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
{ {
numIndicesPerInstance = count; numIndicesPerInstance = count;
} }
const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs(); return mInputLayoutCache.applyVertexBuffers(state, mTranslatedAttribCache, mode, indexInfo,
const auto &currentValueAttribs = mStateManager.getCurrentValueAttribs(); numIndicesPerInstance);
return mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs,
mode, indexInfo, numIndicesPerInstance);
} }
gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
...@@ -2471,7 +2462,6 @@ void Renderer11::markAllStateDirty() ...@@ -2471,7 +2462,6 @@ void Renderer11::markAllStateDirty()
void Renderer11::releaseDeviceResources() void Renderer11::releaseDeviceResources()
{ {
mStateManager.deinitialize();
mStateCache.clear(); mStateCache.clear();
mInputLayoutCache.clear(); mInputLayoutCache.clear();
...@@ -4302,5 +4292,4 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device) ...@@ -4302,5 +4292,4 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
*device = static_cast<DeviceImpl *>(mEGLDevice); *device = static_cast<DeviceImpl *>(mEGLDevice);
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
}
} // namespace rx
...@@ -150,9 +150,7 @@ StateManager11::StateManager11(Renderer11 *renderer) ...@@ -150,9 +150,7 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurNear(0.0f), mCurNear(0.0f),
mCurFar(0.0f), mCurFar(0.0f),
mViewportBounds(), mViewportBounds(),
mRenderTargetIsDirty(false), mRenderTargetIsDirty(false)
mDirtyCurrentValueAttribs(),
mCurrentValueAttribs()
{ {
mCurBlendState.blend = false; mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE; mCurBlendState.sourceBlendRGB = GL_ONE;
...@@ -193,9 +191,6 @@ StateManager11::StateManager11(Renderer11 *renderer) ...@@ -193,9 +191,6 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurRasterState.polygonOffsetUnits = 0.0f; mCurRasterState.polygonOffsetUnits = 0.0f;
mCurRasterState.pointDrawMode = false; mCurRasterState.pointDrawMode = false;
mCurRasterState.multiSample = false; mCurRasterState.multiSample = false;
// Initially all current value attributes must be updated on first use.
mDirtyCurrentValueAttribs.flip();
} }
StateManager11::~StateManager11() StateManager11::~StateManager11()
...@@ -246,7 +241,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit ...@@ -246,7 +241,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
return; return;
} }
for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
{ {
switch (dirtyBit) switch (dirtyBit)
{ {
...@@ -466,13 +461,6 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit ...@@ -466,13 +461,6 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
mRenderTargetIsDirty = true; mRenderTargetIsDirty = true;
break; break;
default: 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; break;
} }
} }
...@@ -970,13 +958,6 @@ void StateManager11::initialize(const gl::Caps &caps) ...@@ -970,13 +958,6 @@ void StateManager11::initialize(const gl::Caps &caps)
// Initialize cached NULL SRV block // Initialize cached NULL SRV block
mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
mCurrentValueAttribs.resize(caps.maxVertexAttributes);
}
void StateManager11::deinitialize()
{
mCurrentValueAttribs.clear();
} }
gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer)
...@@ -1097,40 +1078,4 @@ 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); 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 } // namespace rx
...@@ -48,7 +48,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -48,7 +48,6 @@ class StateManager11 final : angle::NonCopyable
~StateManager11(); ~StateManager11();
void initialize(const gl::Caps &caps); void initialize(const gl::Caps &caps);
void deinitialize();
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
gl::Error setBlendState(const gl::Framebuffer *framebuffer, gl::Error setBlendState(const gl::Framebuffer *framebuffer,
...@@ -92,11 +91,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -92,11 +91,6 @@ class StateManager11 final : angle::NonCopyable
void onDeleteQueryObject(Query11 *query); void onDeleteQueryObject(Query11 *query);
gl::Error onMakeCurrent(const gl::Data &data); gl::Error onMakeCurrent(const gl::Data &data);
gl::Error updateCurrentValueAttribs(const gl::State &state,
VertexDataManager *vertexDataManager);
const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const;
private: private:
void setViewportBounds(const int width, const int height); void setViewportBounds(const int width, const int height);
void unsetConflictingSRVs(gl::SamplerType shaderType, void unsetConflictingSRVs(gl::SamplerType shaderType,
...@@ -192,10 +186,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -192,10 +186,6 @@ class StateManager11 final : angle::NonCopyable
// A block of NULL pointers, cached so we don't re-allocate every draw call // A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView *> mNullSRVs; std::vector<ID3D11ShaderResourceView *> mNullSRVs;
// Current translations of "Current-Value" data - owned by Context, not VertexArray.
gl::AttributesMask mDirtyCurrentValueAttribs;
std::vector<TranslatedAttribute> mCurrentValueAttribs;
}; };
} // namespace rx } // 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, start);
break;
case VertexStorageType::STATIC:
{
auto error = VertexDataManager::StoreStaticAttrib(translatedAttrib, start,
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);
}
} // namespace rx
...@@ -19,40 +19,13 @@ class Renderer11; ...@@ -19,40 +19,13 @@ class Renderer11;
class VertexArray11 : public VertexArrayImpl class VertexArray11 : public VertexArrayImpl
{ {
public: public:
VertexArray11(const gl::VertexArray::Data &data); VertexArray11(const gl::VertexArray::Data &data)
~VertexArray11() override; : VertexArrayImpl(data)
{
void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override; }
gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, virtual ~VertexArray11() {}
const gl::State &state,
GLint start,
GLsizei count,
GLsizei instances);
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;
}; };
} // namespace rx }
#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
...@@ -1716,40 +1716,4 @@ bool UsePresentPathFast(const Renderer11 *renderer, ...@@ -1716,40 +1716,4 @@ bool UsePresentPathFast(const Renderer11 *renderer,
renderer->presentPathFastEnabled()); 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 } // namespace rx
...@@ -406,21 +406,6 @@ bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachm ...@@ -406,21 +406,6 @@ bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachm
using NotificationCallback = std::function<void()>; 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 } // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
...@@ -154,8 +154,6 @@ void Renderer9::release() ...@@ -154,8 +154,6 @@ void Renderer9::release()
{ {
RendererD3D::cleanup(); RendererD3D::cleanup();
mTranslatedAttribCache.clear();
releaseDeviceResources(); releaseDeviceResources();
SafeDelete(mEGLDevice); SafeDelete(mEGLDevice);
...@@ -366,6 +364,7 @@ void Renderer9::initializeDevice() ...@@ -366,6 +364,7 @@ void Renderer9::initializeDevice()
mVertexDataManager = new VertexDataManager(this); mVertexDataManager = new VertexDataManager(this);
mIndexDataManager = new IndexDataManager(this, getRendererClass()); mIndexDataManager = new IndexDataManager(this, getRendererClass());
// TODO(jmadill): use context caps, and place in common D3D location
mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes); mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
} }
......
...@@ -393,7 +393,6 @@ class Renderer9 : public RendererD3D ...@@ -393,7 +393,6 @@ class Renderer9 : public RendererD3D
UINT mMaxNullColorbufferLRU; UINT mMaxNullColorbufferLRU;
DeviceD3D *mEGLDevice; DeviceD3D *mEGLDevice;
std::vector<TranslatedAttribute> mTranslatedAttribCache;
}; };
} }
......
...@@ -387,7 +387,6 @@ ...@@ -387,7 +387,6 @@
'libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp', '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_autogen.h',
'libANGLE/renderer/d3d/d3d11/texture_format_table.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/VertexArray11.h',
'libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp', 'libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp',
'libANGLE/renderer/d3d/d3d11/VertexBuffer11.h', 'libANGLE/renderer/d3d/d3d11/VertexBuffer11.h',
......
...@@ -207,31 +207,6 @@ TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash) ...@@ -207,31 +207,6 @@ TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash)
delete[] data; 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 class IndexedBufferCopyTest : public ANGLETest
{ {
protected: protected:
......
...@@ -86,11 +86,6 @@ class VertexAttributeTest : public ANGLETest ...@@ -86,11 +86,6 @@ class VertexAttributeTest : public ANGLETest
return; return;
} }
if (mProgram == 0)
{
initBasicProgram();
}
GLint viewportSize[4]; GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize); glGetIntegerv(GL_VIEWPORT, viewportSize);
...@@ -142,6 +137,42 @@ class VertexAttributeTest : public ANGLETest ...@@ -142,6 +137,42 @@ class VertexAttributeTest : public ANGLETest
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
const std::string testVertexShaderSource = SHADER_SOURCE
(
attribute highp vec4 position;
attribute highp vec4 test;
attribute highp vec4 expected;
varying highp vec4 color;
void main(void)
{
gl_Position = position;
vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
color = vec4(lessThanEqual(abs(test - expected), threshold));
}
);
const std::string testFragmentShaderSource = SHADER_SOURCE
(
varying highp vec4 color;
void main(void)
{
gl_FragColor = color;
}
);
mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
if (mProgram == 0)
{
FAIL() << "shader compilation failed.";
}
mTestAttrib = glGetAttribLocation(mProgram, "test");
mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
glUseProgram(mProgram);
glClearColor(0, 0, 0, 0); glClearColor(0, 0, 0, 0);
glClearDepthf(0.0); glClearDepthf(0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...@@ -163,12 +194,12 @@ class VertexAttributeTest : public ANGLETest ...@@ -163,12 +194,12 @@ class VertexAttributeTest : public ANGLETest
{ {
std::stringstream shaderStream; std::stringstream shaderStream;
shaderStream << "attribute mediump vec4 position;" << std::endl; shaderStream << "attribute highp vec4 position;" << std::endl;
for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex) for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
{ {
shaderStream << "attribute float a" << attribIndex << ";" << std::endl; shaderStream << "attribute float a" << attribIndex << ";" << std::endl;
} }
shaderStream << "varying mediump float color;" << std::endl shaderStream << "varying highp float color;" << std::endl
<< "void main() {" << std::endl << "void main() {" << std::endl
<< " gl_Position = position;" << std::endl << " gl_Position = position;" << std::endl
<< " color = 0.0;" << std::endl; << " color = 0.0;" << std::endl;
...@@ -178,11 +209,14 @@ class VertexAttributeTest : public ANGLETest ...@@ -178,11 +209,14 @@ class VertexAttributeTest : public ANGLETest
} }
shaderStream << "}" << std::endl; shaderStream << "}" << std::endl;
const std::string testFragmentShaderSource = const std::string testFragmentShaderSource = SHADER_SOURCE
SHADER_SOURCE(varying mediump float color; void main(void) (
varying highp float color;
void main(void)
{ {
gl_FragColor = vec4(color, 0.0, 0.0, 1.0); gl_FragColor = vec4(color, 0.0, 0.0, 1.0);
}); }
);
return CompileProgram(shaderStream.str(), testFragmentShaderSource); return CompileProgram(shaderStream.str(), testFragmentShaderSource);
} }
...@@ -201,38 +235,6 @@ class VertexAttributeTest : public ANGLETest ...@@ -201,38 +235,6 @@ class VertexAttributeTest : public ANGLETest
} }
} }
void initBasicProgram()
{
const std::string testVertexShaderSource =
"attribute mediump vec4 position;\n"
"attribute mediump vec4 test;\n"
"attribute mediump vec4 expected;\n"
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_Position = position;\n"
" vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
" color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
"}\n";
const std::string testFragmentShaderSource =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
ASSERT_NE(0u, mProgram);
mTestAttrib = glGetAttribLocation(mProgram, "test");
ASSERT_NE(-1, mTestAttrib);
mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
ASSERT_NE(-1, mExpectedAttrib);
glUseProgram(mProgram);
}
static const size_t mVertexCount = 24; static const size_t mVertexCount = 24;
GLuint mProgram; GLuint mProgram;
...@@ -489,72 +491,12 @@ class VertexAttributeCachingTest : public VertexAttributeTest ...@@ -489,72 +491,12 @@ class VertexAttributeCachingTest : public VertexAttributeTest
protected: protected:
VertexAttributeCachingTest() {} VertexAttributeCachingTest() {}
void SetUp() override;
template <typename DestT> template <typename DestT>
static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData, static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
GLenum attribType, GLenum attribType,
GLboolean normalized); GLboolean normalized);
void initDoubleAttribProgram()
{
const std::string testVertexShaderSource =
"attribute mediump vec4 position;\n"
"attribute mediump vec4 test;\n"
"attribute mediump vec4 expected;\n"
"attribute mediump vec4 test2;\n"
"attribute mediump vec4 expected2;\n"
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_Position = position;\n"
" vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
" color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
" vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
" color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
"}\n";
const std::string testFragmentShaderSource =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
ASSERT_NE(0u, mProgram);
mTestAttrib = glGetAttribLocation(mProgram, "test");
ASSERT_NE(-1, mTestAttrib);
mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
ASSERT_NE(-1, mExpectedAttrib);
glUseProgram(mProgram);
}
struct AttribData
{
AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
GLenum type;
GLint size;
GLboolean normalized;
GLsizei stride;
};
std::vector<AttribData> mTestData;
std::map<GLenum, std::vector<GLfloat>> mExpectedData;
std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
}; };
VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
GLint sizeIn,
GLboolean normalizedIn,
GLsizei strideIn)
: type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
{
}
// static // static
template <typename DestT> template <typename DestT>
std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData( std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
...@@ -585,9 +527,17 @@ std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData( ...@@ -585,9 +527,17 @@ std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
return expectedData; return expectedData;
} }
void VertexAttributeCachingTest::SetUp() // In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
// cache management scheme which garbage collects old attributes after we start using too much
// cache data. This test tries to make as many attribute caches from a single buffer as possible
// to stress-test the caching code.
TEST_P(VertexAttributeCachingTest, BufferMulticaching)
{ {
VertexAttributeTest::SetUp(); if (IsAMD() && isOpenGL())
{
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
glBindBuffer(GL_ARRAY_BUFFER, mBuffer); glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
...@@ -605,6 +555,19 @@ void VertexAttributeCachingTest::SetUp() ...@@ -605,6 +555,19 @@ void VertexAttributeCachingTest::SetUp()
GLint viewportSize[4]; GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize); glGetIntegerv(GL_VIEWPORT, viewportSize);
struct AttribData
{
AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn)
: type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
{
}
GLenum type;
GLint size;
GLboolean normalized;
GLsizei stride;
};
std::vector<GLenum> attribTypes; std::vector<GLenum> attribTypes;
attribTypes.push_back(GL_BYTE); attribTypes.push_back(GL_BYTE);
attribTypes.push_back(GL_UNSIGNED_BYTE); attribTypes.push_back(GL_UNSIGNED_BYTE);
...@@ -617,6 +580,8 @@ void VertexAttributeCachingTest::SetUp() ...@@ -617,6 +580,8 @@ void VertexAttributeCachingTest::SetUp()
attribTypes.push_back(GL_UNSIGNED_INT); attribTypes.push_back(GL_UNSIGNED_INT);
} }
std::vector<AttribData> datas;
const GLint maxSize = 4; const GLint maxSize = 4;
const GLsizei maxStride = 4; const GLsizei maxStride = 4;
...@@ -626,56 +591,44 @@ void VertexAttributeCachingTest::SetUp() ...@@ -626,56 +591,44 @@ void VertexAttributeCachingTest::SetUp()
{ {
for (GLsizei stride = 1; stride <= maxStride; ++stride) for (GLsizei stride = 1; stride <= maxStride; ++stride)
{ {
mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride)); datas.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
if (attribType != GL_FLOAT) if (attribType != GL_FLOAT)
{ {
mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride)); datas.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
} }
} }
} }
} }
mExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE); std::map<GLenum, std::vector<GLfloat>> expectedData;
mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE); std::map<GLenum, std::vector<GLfloat>> normExpectedData;
mExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
mExpectedData[GL_UNSIGNED_SHORT] = expectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
expectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
expectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
expectedData[GL_UNSIGNED_SHORT] =
GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE); GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
mExpectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE); expectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE); expectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE); normExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
mNormExpectedData[GL_UNSIGNED_BYTE] = normExpectedData[GL_UNSIGNED_BYTE] =
GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE); GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE); normExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
mNormExpectedData[GL_UNSIGNED_SHORT] = normExpectedData[GL_UNSIGNED_SHORT] =
GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE); GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
mNormExpectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE); normExpectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE); normExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
}
// In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
// cache management scheme which garbage collects old attributes after we start using too much
// cache data. This test tries to make as many attribute caches from a single buffer as possible
// to stress-test the caching code.
TEST_P(VertexAttributeCachingTest, BufferMulticaching)
{
if (IsAMD() && isOpenGL())
{
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
initBasicProgram();
glEnableVertexAttribArray(mTestAttrib); glEnableVertexAttribArray(mTestAttrib);
glEnableVertexAttribArray(mExpectedAttrib); glEnableVertexAttribArray(mExpectedAttrib);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
for (const auto &data : mTestData) for (const auto &data : datas)
{ {
const auto &expected = const auto &expected =
(data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type]; (data.normalized) ? normExpectedData[data.type] : expectedData[data.type];
GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride; GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
GLsizei stride = TypeStride(data.type) * baseStride; GLsizei stride = TypeStride(data.type) * baseStride;
...@@ -691,59 +644,6 @@ TEST_P(VertexAttributeCachingTest, BufferMulticaching) ...@@ -691,59 +644,6 @@ TEST_P(VertexAttributeCachingTest, BufferMulticaching)
} }
} }
// With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
// GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
// calls while changing another vertex attribute enough that it clears the static buffer cache
// after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
{
if (IsAMD() && isOpenGL())
{
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
initDoubleAttribProgram();
GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
ASSERT_NE(-1, testAttrib2Location);
GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
ASSERT_NE(-1, expectedAttrib2Location);
glEnableVertexAttribArray(mTestAttrib);
glEnableVertexAttribArray(mExpectedAttrib);
glEnableVertexAttribArray(testAttrib2Location);
glEnableVertexAttribArray(expectedAttrib2Location);
ASSERT_GL_NO_ERROR();
// Use an attribute that we know must be converted. This is a bit sensitive.
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
mExpectedData[GL_UNSIGNED_SHORT].data());
for (const auto &data : mTestData)
{
const auto &expected =
(data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
GLsizei stride = TypeStride(data.type) * baseStride;
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
sizeof(GLfloat) * baseStride, expected.data());
drawQuad(mProgram, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
// D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels 10_0+, so we should test them separately. // D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels 10_0+, so we should test them separately.
ANGLE_INSTANTIATE_TEST(VertexAttributeTest, ANGLE_INSTANTIATE_TEST(VertexAttributeTest,
......
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