Commit 534bf87b by Cooper Partin Committed by Commit Bot

Implemented instanced rendering for emulated point sprites

Non-instanced PointSprite emulation for lower feature levels is implemented using D3D DrawIndexedInstanced and an instanced vertex buffer containing a pointsprite quad. GL instanced rendering using glDrawArraysInstanced and glDrawElementsInstanced with pointsprite emulation is performed using a for-loop. The loop iterates over each instance to render and adjusts the buffer offsets accordingly. This is not performant and is only used and required by this chosen pointsprite emulation method. Indexed instanced (glDrawElementsInstanced), uses the same offset loop because the vertex buffer containing the data to be rendered has already been expanded using getEmulatedIndexedBuffer(). Expanding the buffer makes the two rendering operations similar enough to share code. BUG=angleproject:1279 TEST=angle_end2end_tests Change-Id: If46cc9f158e29f5518c70ad630b3228f474a9f8b Reviewed-on: https://chromium-review.googlesource.com/321407Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent cfd6b2b6
...@@ -150,7 +150,6 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, ...@@ -150,7 +150,6 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
gl::Buffer *glBuffer, gl::Buffer *glBuffer,
const GLvoid *indices, const GLvoid *indices,
TranslatedIndexData *translated, TranslatedIndexData *translated,
SourceIndexData *sourceData,
bool primitiveRestartFixedIndexEnabled) bool primitiveRestartFixedIndexEnabled)
{ {
// Avoid D3D11's primitive restart index value // Avoid D3D11's primitive restart index value
...@@ -176,13 +175,10 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, ...@@ -176,13 +175,10 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr; BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
translated->indexType = dstType; translated->indexType = dstType;
if (sourceData) translated->srcIndexData.srcBuffer = buffer;
{ translated->srcIndexData.srcIndices = indices;
sourceData->srcBuffer = buffer; translated->srcIndexData.srcIndexType = srcType;
sourceData->srcIndices = indices; translated->srcIndexData.srcCount = count;
sourceData->srcIndexType = srcType;
sourceData->srcCount = count;
}
// Case 1: the indices are passed by pointer, which forces the streaming of index data // Case 1: the indices are passed by pointer, which forces the streaming of index data
if (glBuffer == nullptr) if (glBuffer == nullptr)
......
...@@ -36,6 +36,15 @@ class IndexBuffer; ...@@ -36,6 +36,15 @@ class IndexBuffer;
class BufferD3D; class BufferD3D;
class RendererD3D; class RendererD3D;
struct SourceIndexData
{
BufferD3D *srcBuffer;
const GLvoid *srcIndices;
unsigned int srcCount;
GLenum srcIndexType;
bool srcIndicesChanged;
};
struct TranslatedIndexData struct TranslatedIndexData
{ {
gl::IndexRange indexRange; gl::IndexRange indexRange;
...@@ -46,15 +55,8 @@ struct TranslatedIndexData ...@@ -46,15 +55,8 @@ struct TranslatedIndexData
BufferD3D *storage; BufferD3D *storage;
GLenum indexType; GLenum indexType;
unsigned int serial; unsigned int serial;
};
struct SourceIndexData SourceIndexData srcIndexData;
{
BufferD3D *srcBuffer;
const GLvoid *srcIndices;
unsigned int srcCount;
GLenum srcIndexType;
bool srcIndicesChanged;
}; };
class IndexDataManager : angle::NonCopyable class IndexDataManager : angle::NonCopyable
...@@ -68,7 +70,6 @@ class IndexDataManager : angle::NonCopyable ...@@ -68,7 +70,6 @@ class IndexDataManager : angle::NonCopyable
gl::Buffer *glBuffer, gl::Buffer *glBuffer,
const GLvoid *indices, const GLvoid *indices,
TranslatedIndexData *translated, TranslatedIndexData *translated,
SourceIndexData *sourceData,
bool primitiveRestartFixedIndexEnabled); bool primitiveRestartFixedIndexEnabled);
private: private:
......
...@@ -156,9 +156,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, ...@@ -156,9 +156,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
TranslatedIndexData indexInfo; TranslatedIndexData indexInfo;
indexInfo.indexRange = indexRange; indexInfo.indexRange = indexRange;
SourceIndexData sourceIndexInfo; error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo);
error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo, &sourceIndexInfo);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -171,7 +169,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, ...@@ -171,7 +169,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
size_t vertexCount = indexInfo.indexRange.vertexCount(); size_t vertexCount = indexInfo.indexRange.vertexCount();
error = applyVertexBuffer(*data.state, mode, static_cast<GLsizei>(indexInfo.indexRange.start), error = applyVertexBuffer(*data.state, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
static_cast<GLsizei>(vertexCount), instances, &sourceIndexInfo); static_cast<GLsizei>(vertexCount), instances, &indexInfo);
if (error.isError()) if (error.isError())
{ {
return error; return error;
......
...@@ -162,14 +162,18 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -162,14 +162,18 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
GLenum drawMode, GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) = 0; const std::vector<D3DUniform *> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo) = 0; virtual gl::Error applyVertexBuffer(const gl::State &state,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData *indexInfo) = 0;
virtual gl::Error applyIndexBuffer(const gl::Data &data, virtual gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices, const GLvoid *indices,
GLsizei count, GLsizei count,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo) = 0;
SourceIndexData *sourceIndexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
virtual unsigned int getReservedVertexUniformVectors() const = 0; virtual unsigned int getReservedVertexUniformVectors() const = 0;
......
...@@ -27,6 +27,11 @@ namespace rx ...@@ -27,6 +27,11 @@ namespace rx
namespace namespace
{ {
size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
{
return usesPointSpriteEmulation ? 1 : 0;
}
gl::InputLayout GetInputLayout(const SortedAttribArray &translatedAttributes, size_t attributeCount) gl::InputLayout GetInputLayout(const SortedAttribArray &translatedAttributes, size_t attributeCount)
{ {
gl::InputLayout inputLayout(attributeCount, gl::VERTEX_FORMAT_INVALID); gl::InputLayout inputLayout(attributeCount, gl::VERTEX_FORMAT_INVALID);
...@@ -131,13 +136,13 @@ bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLay ...@@ -131,13 +136,13 @@ bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLay
return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0; return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0;
} }
InputLayoutCache::InputLayoutCache() InputLayoutCache::InputLayoutCache() : mCacheSize(kDefaultCacheSize), mUnsortedAttributesCount(0)
: mCacheSize(kDefaultCacheSize)
{ {
mCounter = 0; mCounter = 0;
mDevice = NULL; mDevice = NULL;
mDeviceContext = NULL; mDeviceContext = NULL;
mCurrentIL = NULL; mCurrentIL = NULL;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{ {
mCurrentBuffers[i] = NULL; mCurrentBuffers[i] = NULL;
...@@ -182,10 +187,15 @@ void InputLayoutCache::markDirty() ...@@ -182,10 +187,15 @@ void InputLayoutCache::markDirty()
mCurrentVertexStrides[i] = static_cast<UINT>(-1); mCurrentVertexStrides[i] = static_cast<UINT>(-1);
mCurrentVertexOffsets[i] = static_cast<UINT>(-1); mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
} }
mUnsortedAttributesCount = 0;
} }
gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttribute> &unsortedAttributes, gl::Error InputLayoutCache::applyVertexBuffers(
GLenum mode, gl::Program *program, SourceIndexData *sourceInfo) const std::vector<TranslatedAttribute> &unsortedAttributes,
GLenum mode,
gl::Program *program,
TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance)
{ {
ASSERT(mDevice && mDeviceContext); ASSERT(mDevice && mDeviceContext);
...@@ -195,29 +205,30 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri ...@@ -195,29 +205,30 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
SortedIndexArray sortedSemanticIndices; SortedIndexArray sortedSemanticIndices;
SortedAttribArray sortedAttributes; mSortedAttributes.fill(nullptr);
sortedAttributes.fill(nullptr); mUnsortedAttributesCount = unsortedAttributes.size();
programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(), programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(),
sortedAttributes.data()); mSortedAttributes.data());
// 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
if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !unsortedAttributes.empty()) if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !unsortedAttributes.empty())
{ {
if (sortedAttributes[0]->divisor > 0) if (mSortedAttributes[0]->divisor > 0)
{ {
Optional<size_t> firstNonInstancedIndex = Optional<size_t> firstNonInstancedIndex =
FindFirstNonInstanced(sortedAttributes, unsortedAttributes.size()); FindFirstNonInstanced(mSortedAttributes, unsortedAttributes.size());
if (firstNonInstancedIndex.valid()) if (firstNonInstancedIndex.valid())
{ {
size_t index = firstNonInstancedIndex.value(); size_t index = firstNonInstancedIndex.value();
std::swap(sortedAttributes[0], sortedAttributes[index]); std::swap(mSortedAttributes[0], mSortedAttributes[index]);
std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
} }
} }
} }
gl::Error error = updateInputLayout(program, mode, sortedAttributes, sortedSemanticIndices, gl::Error error = updateInputLayout(program, mode, mSortedAttributes, sortedSemanticIndices,
unsortedAttributes.size()); unsortedAttributes.size(), numIndicesPerInstance);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -228,7 +239,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri ...@@ -228,7 +239,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
size_t maxDiff = 0; size_t maxDiff = 0;
// Note that if we use instance emulation, we reserve the first buffer slot. // Note that if we use instance emulation, we reserve the first buffer slot.
size_t reservedBuffers = programUsesInstancedPointSprites ? 1 : 0; size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers); for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
++attribIndex) ++attribIndex)
...@@ -237,7 +248,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri ...@@ -237,7 +248,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
UINT vertexStride = 0; UINT vertexStride = 0;
UINT vertexOffset = 0; UINT vertexOffset = 0;
const auto &attrib = *sortedAttributes[attribIndex]; const auto &attrib = *mSortedAttributes[attribIndex];
if (attribIndex < unsortedAttributes.size() && attrib.active) if (attribIndex < unsortedAttributes.size() && attrib.active)
{ {
...@@ -252,24 +263,25 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri ...@@ -252,24 +263,25 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
{ {
buffer = vertexBuffer->getBuffer(); buffer = vertexBuffer->getBuffer();
} }
else if (instancedPointSpritesActive && (sourceInfo != nullptr)) else if (instancedPointSpritesActive && (indexInfo != nullptr))
{ {
if (sourceInfo->srcBuffer != nullptr) if (indexInfo->srcIndexData.srcBuffer != nullptr)
{ {
const uint8_t *bufferData = nullptr; const uint8_t *bufferData = nullptr;
error = sourceInfo->srcBuffer->getData(&bufferData); error = indexInfo->srcIndexData.srcBuffer->getData(&bufferData);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
ASSERT(bufferData != nullptr); ASSERT(bufferData != nullptr);
ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(sourceInfo->srcIndices); ptrdiff_t offset =
sourceInfo->srcBuffer = nullptr; reinterpret_cast<ptrdiff_t>(indexInfo->srcIndexData.srcIndices);
sourceInfo->srcIndices = bufferData + offset; indexInfo->srcIndexData.srcBuffer = nullptr;
indexInfo->srcIndexData.srcIndices = bufferData + offset;
} }
buffer = bufferStorage->getEmulatedIndexedBuffer(sourceInfo, &attrib); buffer = bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, &attrib);
} }
else else
{ {
...@@ -395,11 +407,33 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri ...@@ -395,11 +407,33 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId)
{
size_t reservedBuffers = GetReservedBufferCount(true);
for (size_t attribIndex = 0; attribIndex < mUnsortedAttributesCount; ++attribIndex)
{
const auto &attrib = *mSortedAttributes[attribIndex];
size_t bufferIndex = reservedBuffers + attribIndex;
if (attrib.active && attrib.divisor > 0)
{
mCurrentVertexOffsets[bufferIndex] =
attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
}
}
mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers,
mCurrentVertexStrides, mCurrentVertexOffsets);
return gl::Error(GL_NO_ERROR);
}
gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, gl::Error InputLayoutCache::updateInputLayout(gl::Program *program,
GLenum mode, GLenum mode,
const SortedAttribArray &sortedAttributes, const SortedAttribArray &sortedAttributes,
const SortedIndexArray &sortedSemanticIndices, const SortedIndexArray &sortedSemanticIndices,
size_t attribCount) size_t attribCount,
GLsizei numIndicesPerInstance)
{ {
const std::vector<sh::Attribute> &shaderAttributes = program->getAttributes(); const std::vector<sh::Attribute> &shaderAttributes = program->getAttributes();
PackedAttributeLayout layout; PackedAttributeLayout layout;
...@@ -419,6 +453,11 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, ...@@ -419,6 +453,11 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program,
layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE; layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
} }
if (numIndicesPerInstance > 0)
{
layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
}
const auto &semanticToLocation = programD3D->getAttributesByLayout(); const auto &semanticToLocation = programD3D->getAttributesByLayout();
for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
...@@ -450,8 +489,9 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, ...@@ -450,8 +489,9 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program,
} }
else else
{ {
gl::Error error = createInputLayout(sortedAttributes, sortedSemanticIndices, gl::Error error =
attribCount, mode, program, &inputLayout); createInputLayout(sortedAttributes, sortedSemanticIndices, attribCount, mode,
program, numIndicesPerInstance, &inputLayout);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -493,6 +533,7 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt ...@@ -493,6 +533,7 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt
size_t attribCount, size_t attribCount,
GLenum mode, GLenum mode,
gl::Program *program, gl::Program *program,
GLsizei numIndicesPerInstance,
ID3D11InputLayout **inputLayoutOut) ID3D11InputLayout **inputLayoutOut)
{ {
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
...@@ -553,6 +594,10 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt ...@@ -553,6 +594,10 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt
{ {
inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
inputElements[elementIndex].InstanceDataStepRate = 1; inputElements[elementIndex].InstanceDataStepRate = 1;
if (numIndicesPerInstance > 0 && sortedAttributes[elementIndex]->divisor > 0)
{
inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
}
} }
inputElements[elementIndex].InputSlot++; inputElements[elementIndex].InputSlot++;
} }
......
...@@ -48,7 +48,12 @@ class InputLayoutCache : angle::NonCopyable ...@@ -48,7 +48,12 @@ class InputLayoutCache : angle::NonCopyable
void markDirty(); void markDirty();
gl::Error applyVertexBuffers(const std::vector<TranslatedAttribute> &attributes, gl::Error applyVertexBuffers(const std::vector<TranslatedAttribute> &attributes,
GLenum mode, gl::Program *program, SourceIndexData *sourceInfo); GLenum mode,
gl::Program *program,
TranslatedIndexData *indexInfo,
GLsizei numIndicesPerInstance);
gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId);
// Useful for testing // Useful for testing
void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; } void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; }
...@@ -71,8 +76,9 @@ class InputLayoutCache : angle::NonCopyable ...@@ -71,8 +76,9 @@ class InputLayoutCache : angle::NonCopyable
enum Flags enum Flags
{ {
FLAG_USES_INSTANCED_SPRITES = 0x1, FLAG_USES_INSTANCED_SPRITES = 0x1,
FLAG_INSTANCED_SPRITES_ACTIVE = 0x2, FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
}; };
size_t numAttributes; size_t numAttributes;
...@@ -84,12 +90,14 @@ class InputLayoutCache : angle::NonCopyable ...@@ -84,12 +90,14 @@ class InputLayoutCache : angle::NonCopyable
GLenum mode, GLenum mode,
const SortedAttribArray &sortedAttributes, const SortedAttribArray &sortedAttributes,
const SortedIndexArray &sortedSemanticIndices, const SortedIndexArray &sortedSemanticIndices,
size_t attribCount); size_t attribCount,
GLsizei numIndicesPerInstance);
gl::Error createInputLayout(const SortedAttribArray &sortedAttributes, gl::Error createInputLayout(const SortedAttribArray &sortedAttributes,
const SortedIndexArray &sortedSemanticIndices, const SortedIndexArray &sortedSemanticIndices,
size_t attribCount, size_t attribCount,
GLenum mode, GLenum mode,
gl::Program *program, gl::Program *program,
GLsizei numIndicesPerInstance,
ID3D11InputLayout **inputLayoutOut); ID3D11InputLayout **inputLayoutOut);
std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap; std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
...@@ -98,6 +106,8 @@ class InputLayoutCache : angle::NonCopyable ...@@ -98,6 +106,8 @@ class InputLayoutCache : angle::NonCopyable
ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
SortedAttribArray mSortedAttributes;
size_t mUnsortedAttributesCount;
ID3D11Buffer *mPointSpriteVertexBuffer; ID3D11Buffer *mPointSpriteVertexBuffer;
ID3D11Buffer *mPointSpriteIndexBuffer; ID3D11Buffer *mPointSpriteIndexBuffer;
......
...@@ -1476,7 +1476,12 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) ...@@ -1476,7 +1476,12 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
return mStateManager.syncFramebuffer(framebuffer); return mStateManager.syncFramebuffer(framebuffer);
} }
gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo) gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData *indexInfo)
{ {
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
if (error.isError()) if (error.isError())
...@@ -1485,12 +1490,18 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi ...@@ -1485,12 +1490,18 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi
} }
// If index information is passed, mark it with the current changed status. // If index information is passed, mark it with the current changed status.
if (sourceInfo) if (indexInfo)
{ {
sourceInfo->srcIndicesChanged = mAppliedIBChanged; indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged;
} }
return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), sourceInfo); GLsizei numIndicesPerInstance = 0;
if (instances > 0)
{
numIndicesPerInstance = count;
}
return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(),
indexInfo, numIndicesPerInstance);
} }
gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
...@@ -1498,14 +1509,13 @@ gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, ...@@ -1498,14 +1509,13 @@ gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
GLsizei count, GLsizei count,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo)
SourceIndexData *sourceIndexInfo)
{ {
gl::VertexArray *vao = data.state->getVertexArray(); gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, gl::Error error =
indexInfo, sourceIndexInfo, mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo,
data.state->isPrimitiveRestartEnabled()); data.state->isPrimitiveRestartEnabled());
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -1676,15 +1686,39 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, ...@@ -1676,15 +1686,39 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
} }
bool useInstancedPointSpriteEmulation =
programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
if (instances > 0) if (instances > 0)
{ {
mDeviceContext->DrawInstanced(count, instances, 0, 0); if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
{
// If pointsprite emulation is used with glDrawArraysInstanced then we need to take a
// less efficent code path.
// Instanced rendering of emulated pointsprites requires a loop to draw each batch of
// points. An offset into the instanced data buffer is calculated and applied on each
// iteration to ensure all instances are rendered correctly.
// Each instance being rendered requires the inputlayout cache to reapply buffers and
// offsets.
for (GLsizei i = 0; i < instances; i++)
{
gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
if (error.isError())
{
return error;
}
mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
}
}
else
{
mDeviceContext->DrawInstanced(count, instances, 0, 0);
}
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
bool useInstancedPointSpriteEmulation =
programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
// If the shader is writing to gl_PointSize, then pointsprites are being rendered. // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
// Emulating instanced point sprites for FL9_3 requires the topology to be // Emulating instanced point sprites for FL9_3 requires the topology to be
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
...@@ -1719,16 +1753,41 @@ gl::Error Renderer11::drawElementsImpl(const gl::Data &data, ...@@ -1719,16 +1753,41 @@ gl::Error Renderer11::drawElementsImpl(const gl::Data &data,
return drawTriangleFan(data, count, type, indices, minIndex, instances); return drawTriangleFan(data, count, type, indices, minIndex, instances);
} }
const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
if (instances > 0) if (instances > 0)
{ {
mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
{
// If pointsprite emulation is used with glDrawElementsInstanced then we need to take a
// less efficent code path.
// Instanced rendering of emulated pointsprites requires a loop to draw each batch of
// points. An offset into the instanced data buffer is calculated and applied on each
// iteration to ensure all instances are rendered correctly.
GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount());
// Each instance being rendered requires the inputlayout cache to reapply buffers and
// offsets.
for (GLsizei i = 0; i < instances; i++)
{
gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
if (error.isError())
{
return error;
}
mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
}
}
else
{
mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
}
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
// If the shader is writing to gl_PointSize, then pointsprites are being rendered. // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
// Emulating instanced point sprites for FL9_3 requires the topology to be // Emulating instanced point sprites for FL9_3 requires the topology to be
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
{ {
// The count parameter passed to drawElements represents the total number of instances // The count parameter passed to drawElements represents the total number of instances
......
...@@ -135,14 +135,18 @@ class Renderer11 : public RendererD3D ...@@ -135,14 +135,18 @@ class Renderer11 : public RendererD3D
gl::Error applyUniforms(const ProgramD3D &programD3D, gl::Error applyUniforms(const ProgramD3D &programD3D,
GLenum drawMode, GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override; const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo); virtual gl::Error applyVertexBuffer(const gl::State &state,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData *indexInfo);
gl::Error applyIndexBuffer(const gl::Data &data, gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices, const GLvoid *indices,
GLsizei count, GLsizei count,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo) override;
SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override; void applyTransformFeedbackBuffers(const gl::State &state) override;
// lost device // lost device
......
...@@ -1171,7 +1171,12 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) ...@@ -1171,7 +1171,12 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer()); return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer());
} }
gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData * /*sourceInfo*/) gl::Error Renderer9::applyVertexBuffer(const gl::State &state,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData * /*indexInfo*/)
{ {
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
if (error.isError()) if (error.isError())
...@@ -1188,13 +1193,12 @@ gl::Error Renderer9::applyIndexBuffer(const gl::Data &data, ...@@ -1188,13 +1193,12 @@ gl::Error Renderer9::applyIndexBuffer(const gl::Data &data,
GLsizei count, GLsizei count,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo)
SourceIndexData *sourceIndexInfo)
{ {
gl::VertexArray *vao = data.state->getVertexArray(); gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
indexInfo, sourceIndexInfo, false); indexInfo, false);
if (error.isError()) if (error.isError())
{ {
return error; return error;
......
...@@ -121,14 +121,18 @@ class Renderer9 : public RendererD3D ...@@ -121,14 +121,18 @@ class Renderer9 : public RendererD3D
GLenum drawMode, GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override; const std::vector<D3DUniform *> &uniformArray) override;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo); virtual gl::Error applyVertexBuffer(const gl::State &state,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData *indexInfo);
gl::Error applyIndexBuffer(const gl::Data &data, gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices, const GLvoid *indices,
GLsizei count, GLsizei count,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo, TranslatedIndexData *indexInfo) override;
SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override; void applyTransformFeedbackBuffers(const gl::State &state) override;
......
...@@ -11,7 +11,7 @@ using namespace angle; ...@@ -11,7 +11,7 @@ using namespace angle;
class InstancingTest : public ANGLETest class InstancingTest : public ANGLETest
{ {
protected: protected:
InstancingTest() InstancingTest() : mProgram(0), mVertexBuffer(0)
{ {
setWindowWidth(256); setWindowWidth(256);
setWindowHeight(256); setWindowHeight(256);
...@@ -21,7 +21,13 @@ class InstancingTest : public ANGLETest ...@@ -21,7 +21,13 @@ class InstancingTest : public ANGLETest
setConfigAlphaBits(8); setConfigAlphaBits(8);
} }
virtual void SetUp() ~InstancingTest() override
{
glDeleteBuffers(1, &mVertexBuffer);
glDeleteProgram(mProgram);
}
void SetUp() override
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
...@@ -93,10 +99,12 @@ class InstancingTest : public ANGLETest ...@@ -93,10 +99,12 @@ class InstancingTest : public ANGLETest
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glGenBuffers(1, &mVertexBuffer);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
GLuint setupDrawArraysTest(const std::string &vs) void setupDrawArraysTest(const std::string &vs)
{ {
const std::string fs = SHADER_SOURCE const std::string fs = SHADER_SOURCE
( (
...@@ -107,11 +115,8 @@ class InstancingTest : public ANGLETest ...@@ -107,11 +115,8 @@ class InstancingTest : public ANGLETest
} }
); );
GLuint program = CompileProgram(vs, fs); mProgram = CompileProgram(vs, fs);
if (program == 0) ASSERT_NE(0u, mProgram);
{
return 0;
}
// Set the viewport // Set the viewport
glViewport(0, 0, getWindowWidth(), getWindowHeight()); glViewport(0, 0, getWindowWidth(), getWindowHeight());
...@@ -120,30 +125,69 @@ class InstancingTest : public ANGLETest ...@@ -120,30 +125,69 @@ class InstancingTest : public ANGLETest
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// Use the program object // Use the program object
glUseProgram(program); glUseProgram(mProgram);
return program;
} }
void runDrawArraysTest(GLuint program, GLint first, GLsizei count, GLsizei instanceCount, float *offset) void setupInstancedPointsTest()
{ {
GLuint vertexBuffer; mIndices.clear();
glGenBuffers(1, &vertexBuffer); mIndices.push_back(0);
mIndices.push_back(1);
mIndices.push_back(2);
mIndices.push_back(3);
// clang-format off
const std::string vs = SHADER_SOURCE
(
attribute vec3 a_position;
attribute vec3 a_instancePos;
void main()
{
gl_Position = vec4(a_position.xyz, 1.0);
gl_Position = vec4(a_instancePos.xyz, 1.0);
gl_PointSize = 6.0;
}
);
const std::string fs = SHADER_SOURCE
(
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0, 0, 1.0);
}
);
// clang-format on
mProgram = CompileProgram(vs, fs);
ASSERT_NE(0u, mProgram);
// Set the viewport
glViewport(0, 0, getWindowWidth(), getWindowHeight());
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(mProgram);
}
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); void runDrawArraysTest(GLint first, GLsizei count, GLsizei instanceCount, float *offset)
{
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
// Get the attribute locations // Get the attribute locations
GLint positionLoc = glGetAttribLocation(program, "a_position"); GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
GLint instancePosLoc = glGetAttribLocation(program, "a_instancePos"); GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
// Load the vertex position // Load the vertex position
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, mNonIndexedVertices.data()); glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, mNonIndexedVertices.data());
glEnableVertexAttribArray(positionLoc); glEnableVertexAttribArray(positionLoc);
// Load the instance position // Load the instance position
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(instancePosLoc); glEnableVertexAttribArray(instancePosLoc);
...@@ -152,7 +196,7 @@ class InstancingTest : public ANGLETest ...@@ -152,7 +196,7 @@ class InstancingTest : public ANGLETest
mVertexAttribDivisorANGLE(instancePosLoc, 1); mVertexAttribDivisorANGLE(instancePosLoc, 1);
// Offset // Offset
GLint uniformLoc = glGetUniformLocation(program, "u_offset"); GLint uniformLoc = glGetUniformLocation(mProgram, "u_offset");
ASSERT_NE(uniformLoc, -1); ASSERT_NE(uniformLoc, -1);
glUniform3fv(uniformLoc, 1, offset); glUniform3fv(uniformLoc, 1, offset);
...@@ -240,6 +284,9 @@ class InstancingTest : public ANGLETest ...@@ -240,6 +284,9 @@ class InstancingTest : public ANGLETest
std::vector<GLushort> mIndices; std::vector<GLushort> mIndices;
const GLfloat quadRadius = 0.30f; const GLfloat quadRadius = 0.30f;
GLuint mProgram;
GLuint mVertexBuffer;
}; };
class InstancingTestAllConfigs : public InstancingTest class InstancingTestAllConfigs : public InstancingTest
...@@ -254,6 +301,12 @@ class InstancingTestNo9_3 : public InstancingTest ...@@ -254,6 +301,12 @@ class InstancingTestNo9_3 : public InstancingTest
InstancingTestNo9_3() {} InstancingTestNo9_3() {}
}; };
class InstancingTestPoints : public InstancingTest
{
protected:
InstancingTestPoints() {}
};
// This test uses a vertex shader with the first attribute (attribute zero) instanced. // This test uses a vertex shader with the first attribute (attribute zero) instanced.
// On D3D9 and D3D11 FL9_3, this triggers a special codepath that rearranges the input layout sent to D3D, // On D3D9 and D3D11 FL9_3, this triggers a special codepath that rearranges the input layout sent to D3D,
// to ensure that slot/stream zero of the input layout doesn't contain per-instance data. // to ensure that slot/stream zero of the input layout doesn't contain per-instance data.
...@@ -304,18 +357,100 @@ TEST_P(InstancingTestNo9_3, DrawArraysWithOffset) ...@@ -304,18 +357,100 @@ TEST_P(InstancingTestNo9_3, DrawArraysWithOffset)
} }
); );
GLuint program = setupDrawArraysTest(vs); setupDrawArraysTest(vs);
ASSERT_NE(program, 0u);
float offset1[3] = { 0, 0, 0 }; float offset1[3] = { 0, 0, 0 };
runDrawArraysTest(program, 0, 6, 2, offset1); runDrawArraysTest(0, 6, 2, offset1);
float offset2[3] = { 0.0f, 1.0f, 0 }; float offset2[3] = { 0.0f, 1.0f, 0 };
runDrawArraysTest(program, 6, 6, 2, offset2); runDrawArraysTest(6, 6, 2, offset2);
checkQuads();
}
// This test verifies instancing with GL_POINTS with glDrawArraysInstanced works.
// On D3D11 FL9_3, this triggers a special codepath that emulates instanced points rendering.
TEST_P(InstancingTestPoints, DrawArrays)
{
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
// On Win7, the D3D SDK Layers emits a false warning for these tests.
// This doesn't occur on Windows 10 (Version 1511) though.
ignoreD3D11SDKLayersWarnings();
setupInstancedPointsTest();
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0],
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Get the attribute locations
GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
// Load the vertex position
GLfloat pos[3] = {0, 0, 0};
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, pos);
glEnableVertexAttribArray(positionLoc);
// Load the instance position
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(instancePosLoc);
// Enable instancing
mVertexAttribDivisorANGLE(instancePosLoc, 1);
// Do the instanced draw
mDrawArraysInstancedANGLE(GL_POINTS, 0, 1, static_cast<GLsizei>(mInstances.size()) / 3);
ASSERT_GL_NO_ERROR();
checkQuads(); checkQuads();
}
// This test verifies instancing with GL_POINTS with glDrawElementsInstanced works.
// On D3D11 FL9_3, this triggers a special codepath that emulates instanced points rendering.
TEST_P(InstancingTestPoints, DrawElements)
{
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
// On Win7, the D3D SDK Layers emits a false warning for these tests.
// This doesn't occur on Windows 10 (Version 1511) though.
ignoreD3D11SDKLayersWarnings();
setupInstancedPointsTest();
glDeleteProgram(program); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0],
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Get the attribute locations
GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
// Load the vertex position
GLfloat pos[3] = {0, 0, 0};
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, pos);
glEnableVertexAttribArray(positionLoc);
// Load the instance position
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(instancePosLoc);
// Enable instancing
mVertexAttribDivisorANGLE(instancePosLoc, 1);
// Do the instanced draw
mDrawElementsInstancedANGLE(GL_POINTS, static_cast<GLsizei>(mIndices.size()), GL_UNSIGNED_SHORT,
mIndices.data(), static_cast<GLsizei>(mInstances.size()) / 3);
ASSERT_GL_NO_ERROR();
checkQuads();
} }
// 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.
...@@ -329,3 +464,5 @@ ANGLE_INSTANTIATE_TEST(InstancingTestAllConfigs, ...@@ -329,3 +464,5 @@ ANGLE_INSTANTIATE_TEST(InstancingTestAllConfigs,
// TODO(jmadill): Figure out the situation with DrawInstanced on FL 9_3 // TODO(jmadill): Figure out the situation with DrawInstanced on FL 9_3
ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11()); ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3());
...@@ -154,13 +154,12 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest() ...@@ -154,13 +154,12 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest()
void IndexDataManagerPerfTest::step() void IndexDataManagerPerfTest::step()
{ {
rx::TranslatedIndexData translatedIndexData; rx::TranslatedIndexData translatedIndexData;
rx::SourceIndexData sourceIndexData;
for (unsigned int iteration = 0; iteration < 100; ++iteration) for (unsigned int iteration = 0; iteration < 100; ++iteration)
{ {
mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, false, mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, false,
&translatedIndexData.indexRange); &translatedIndexData.indexRange);
mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr, mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr,
&translatedIndexData, &sourceIndexData, false); &translatedIndexData, false);
} }
} }
......
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