Commit e6124500 by shrekshao Committed by Commit Bot

Fix baseVertex and baseInstance with streaming attributes

baseInstance: Fixed by adding the intial offset to each copy for streaming attributes baseVertex: make sure mShaderConstants.onFirstVertexChange takes in correct firstVertex value for dynamic attribs (where firstVertex passed to StateManager11::updateState already include baseVertex) Bug: chromium:1078330, angleproject:3402 Change-Id: I289c4e3733fdf6f78af8c3adee84112c05a5abce Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2227022Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Shrek Shao <shrekshao@google.com>
parent 7f7d046b
...@@ -141,6 +141,7 @@ class BufferFactoryD3D : angle::NonCopyable ...@@ -141,6 +141,7 @@ class BufferFactoryD3D : angle::NonCopyable
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *bytesRequiredOut) const = 0; unsigned int *bytesRequiredOut) const = 0;
}; };
......
...@@ -96,11 +96,12 @@ angle::Result VertexBufferInterface::getSpaceRequired(const gl::Context *context ...@@ -96,11 +96,12 @@ angle::Result VertexBufferInterface::getSpaceRequired(const gl::Context *context
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *spaceInBytesOut) const unsigned int *spaceInBytesOut) const
{ {
unsigned int spaceRequired = 0; unsigned int spaceRequired = 0;
ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances, ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
&spaceRequired)); baseInstance, &spaceRequired));
// Align to 16-byte boundary // Align to 16-byte boundary
unsigned int alignedSpaceRequired = roundUpPow2(spaceRequired, 16u); unsigned int alignedSpaceRequired = roundUpPow2(spaceRequired, 16u);
...@@ -171,11 +172,13 @@ angle::Result StreamingVertexBufferInterface::storeDynamicAttribute( ...@@ -171,11 +172,13 @@ angle::Result StreamingVertexBufferInterface::storeDynamicAttribute(
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *outStreamOffset, unsigned int *outStreamOffset,
const uint8_t *sourceData) const uint8_t *sourceData)
{ {
unsigned int spaceRequired = 0; unsigned int spaceRequired = 0;
ANGLE_TRY(getSpaceRequired(context, attrib, binding, count, instances, &spaceRequired)); ANGLE_TRY(
getSpaceRequired(context, attrib, binding, count, instances, baseInstance, &spaceRequired));
// Protect against integer overflow // Protect against integer overflow
angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition); angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
...@@ -184,8 +187,19 @@ angle::Result StreamingVertexBufferInterface::storeDynamicAttribute( ...@@ -184,8 +187,19 @@ angle::Result StreamingVertexBufferInterface::storeDynamicAttribute(
mReservedSpace = 0; mReservedSpace = 0;
size_t adjustedCount = count;
GLuint divisor = binding.getDivisor();
if (instances != 0 && divisor != 0)
{
// The attribute is an instanced attribute and it's an draw instance call
// Extra number of elements are copied at the beginning to make sure
// the driver is referencing the correct data with non-zero baseInstance
adjustedCount += UnsignedCeilDivide(baseInstance, divisor);
}
ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding, currentValueType, ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding, currentValueType,
start, count, instances, mWritePosition, start, adjustedCount, instances, mWritePosition,
sourceData)); sourceData));
if (outStreamOffset) if (outStreamOffset)
...@@ -202,11 +216,12 @@ angle::Result StreamingVertexBufferInterface::reserveVertexSpace(const gl::Conte ...@@ -202,11 +216,12 @@ angle::Result StreamingVertexBufferInterface::reserveVertexSpace(const gl::Conte
const gl::VertexAttribute &attrib, const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances) GLsizei instances,
GLuint baseInstance)
{ {
unsigned int requiredSpace = 0; unsigned int requiredSpace = 0;
ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances, ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
&requiredSpace)); baseInstance, &requiredSpace));
// Align to 16-byte boundary // Align to 16-byte boundary
auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u); auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
...@@ -277,7 +292,7 @@ angle::Result StaticVertexBufferInterface::storeStaticAttribute(const gl::Contex ...@@ -277,7 +292,7 @@ angle::Result StaticVertexBufferInterface::storeStaticAttribute(const gl::Contex
const uint8_t *sourceData) const uint8_t *sourceData)
{ {
unsigned int spaceRequired = 0; unsigned int spaceRequired = 0;
ANGLE_TRY(getSpaceRequired(context, attrib, binding, count, instances, &spaceRequired)); ANGLE_TRY(getSpaceRequired(context, attrib, binding, count, instances, 0, &spaceRequired));
ANGLE_TRY(setBufferSize(context, spaceRequired)); ANGLE_TRY(setBufferSize(context, spaceRequired));
ASSERT(attrib.enabled); ASSERT(attrib.enabled);
......
...@@ -102,6 +102,7 @@ class VertexBufferInterface : angle::NonCopyable ...@@ -102,6 +102,7 @@ class VertexBufferInterface : angle::NonCopyable
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *spaceInBytesOut) const; unsigned int *spaceInBytesOut) const;
BufferFactoryD3D *const mFactory; BufferFactoryD3D *const mFactory;
VertexBuffer *mVertexBuffer; VertexBuffer *mVertexBuffer;
...@@ -124,6 +125,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface ...@@ -124,6 +125,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *outStreamOffset, unsigned int *outStreamOffset,
const uint8_t *sourceData); const uint8_t *sourceData);
...@@ -131,7 +133,8 @@ class StreamingVertexBufferInterface : public VertexBufferInterface ...@@ -131,7 +133,8 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
const gl::VertexAttribute &attribute, const gl::VertexAttribute &attribute,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances); GLsizei instances,
GLuint baseInstance);
private: private:
angle::Result reserveSpace(const gl::Context *context, unsigned int size); angle::Result reserveSpace(const gl::Context *context, unsigned int size);
......
...@@ -114,7 +114,7 @@ bool DirectStoragePossible(const gl::Context *context, ...@@ -114,7 +114,7 @@ bool DirectStoragePossible(const gl::Context *context,
{ {
unsigned int elementSize = 0; unsigned int elementSize = 0;
angle::Result error = angle::Result error =
factory->getVertexSpaceRequired(context, attrib, binding, 1, 0, &elementSize); factory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &elementSize);
ASSERT(error == angle::Result::Continue); ASSERT(error == angle::Result::Continue);
alignment = std::min<size_t>(elementSize, 4); alignment = std::min<size_t>(elementSize, 4);
} }
...@@ -312,8 +312,9 @@ angle::Result VertexDataManager::prepareVertexData( ...@@ -312,8 +312,9 @@ angle::Result VertexDataManager::prepareVertexData(
return angle::Result::Continue; return angle::Result::Continue;
} }
// prepareVertexData is only called by Renderer9 which don't support baseInstance
ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start, ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start,
count, instances)); count, instances, 0u));
PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count); PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count);
...@@ -370,7 +371,7 @@ angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context, ...@@ -370,7 +371,7 @@ angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context,
unsigned int streamOffset = 0; unsigned int streamOffset = 0;
translated->storage = nullptr; translated->storage = nullptr;
ANGLE_TRY(bufferD3D->getFactory()->getVertexSpaceRequired(context, attrib, binding, 1, 0, ANGLE_TRY(bufferD3D->getFactory()->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0,
&translated->stride)); &translated->stride));
auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding); auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding);
...@@ -418,7 +419,8 @@ angle::Result VertexDataManager::storeDynamicAttribs( ...@@ -418,7 +419,8 @@ angle::Result VertexDataManager::storeDynamicAttribs(
const gl::AttributesMask &dynamicAttribsMask, const gl::AttributesMask &dynamicAttribsMask,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances) GLsizei instances,
GLuint baseInstance)
{ {
// Instantiating this class will ensure the streaming buffer is never left mapped. // Instantiating this class will ensure the streaming buffer is never left mapped.
class StreamingBufferUnmapper final : NonCopyable class StreamingBufferUnmapper final : NonCopyable
...@@ -442,14 +444,16 @@ angle::Result VertexDataManager::storeDynamicAttribs( ...@@ -442,14 +444,16 @@ angle::Result VertexDataManager::storeDynamicAttribs(
for (auto attribIndex : dynamicAttribsMask) for (auto attribIndex : dynamicAttribsMask)
{ {
const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
ANGLE_TRY(reserveSpaceForAttrib(context, dynamicAttrib, start, count, instances)); ANGLE_TRY(
reserveSpaceForAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
} }
// Store dynamic attributes // Store dynamic attributes
for (auto attribIndex : dynamicAttribsMask) for (auto attribIndex : dynamicAttribsMask)
{ {
auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
ANGLE_TRY(storeDynamicAttrib(context, dynamicAttrib, start, count, instances)); ANGLE_TRY(
storeDynamicAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -482,7 +486,8 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex ...@@ -482,7 +486,8 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex
const TranslatedAttribute &translatedAttrib, const TranslatedAttribute &translatedAttrib,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances) GLsizei instances,
GLuint baseInstance)
{ {
ASSERT(translatedAttrib.attribute && translatedAttrib.binding); ASSERT(translatedAttrib.attribute && translatedAttrib.binding);
const auto &attrib = *translatedAttrib.attribute; const auto &attrib = *translatedAttrib.attribute;
...@@ -502,7 +507,9 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex ...@@ -502,7 +507,9 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex
{ {
// Vertices do not apply the 'start' offset when the divisor is non-zero even when doing // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
// a non-instanced draw call // a non-instanced draw call
GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start; GLint firstVertexIndex = binding.getDivisor() > 0
? UnsignedCeilDivide(baseInstance, binding.getDivisor())
: start;
int64_t maxVertexCount = int64_t maxVertexCount =
static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount); static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
...@@ -513,14 +520,16 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex ...@@ -513,14 +520,16 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex
maxByte <= static_cast<int64_t>(bufferD3D->getSize()), maxByte <= static_cast<int64_t>(bufferD3D->getSize()),
"Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION); "Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION);
} }
return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances); return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances,
baseInstance);
} }
angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context, angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context,
TranslatedAttribute *translated, TranslatedAttribute *translated,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances) GLsizei instances,
GLuint baseInstance)
{ {
ASSERT(translated->attribute && translated->binding); ASSERT(translated->attribute && translated->binding);
const auto &attrib = *translated->attribute; const auto &attrib = *translated->attribute;
...@@ -533,7 +542,8 @@ angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context, ...@@ -533,7 +542,8 @@ angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context,
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
// Instanced vertices do not apply the 'start' offset // Instanced vertices do not apply the 'start' offset
GLint firstVertexIndex = (binding.getDivisor() > 0 ? 0 : start); GLint firstVertexIndex =
(binding.getDivisor() > 0 ? UnsignedCeilDivide(baseInstance, binding.getDivisor()) : start);
// Compute source data pointer // Compute source data pointer
const uint8_t *sourceData = nullptr; const uint8_t *sourceData = nullptr;
...@@ -554,14 +564,14 @@ angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context, ...@@ -554,14 +564,14 @@ angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context,
translated->storage = nullptr; translated->storage = nullptr;
ANGLE_TRY( ANGLE_TRY(
mFactory->getVertexSpaceRequired(context, attrib, binding, 1, 0, &translated->stride)); mFactory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &translated->stride));
size_t totalCount = gl::ComputeVertexBindingElementCount(binding.getDivisor(), count, size_t totalCount = gl::ComputeVertexBindingElementCount(binding.getDivisor(), count,
static_cast<size_t>(instances)); static_cast<size_t>(instances));
ANGLE_TRY(mStreamingBuffer.storeDynamicAttribute( ANGLE_TRY(mStreamingBuffer.storeDynamicAttribute(
context, attrib, binding, translated->currentValueType, firstVertexIndex, context, attrib, binding, translated->currentValueType, firstVertexIndex,
static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData)); static_cast<GLsizei>(totalCount), instances, baseInstance, &streamOffset, sourceData));
VertexBuffer *vertexBuffer = mStreamingBuffer.getVertexBuffer(); VertexBuffer *vertexBuffer = mStreamingBuffer.getVertexBuffer();
...@@ -593,13 +603,13 @@ angle::Result VertexDataManager::storeCurrentValue( ...@@ -593,13 +603,13 @@ angle::Result VertexDataManager::storeCurrentValue(
const auto &attrib = *translated->attribute; const auto &attrib = *translated->attribute;
const auto &binding = *translated->binding; const auto &binding = *translated->binding;
ANGLE_TRY(buffer.reserveVertexSpace(context, attrib, binding, 1, 0)); ANGLE_TRY(buffer.reserveVertexSpace(context, attrib, binding, 1, 0, 0));
const uint8_t *sourceData = const uint8_t *sourceData =
reinterpret_cast<const uint8_t *>(currentValue.Values.FloatValues); reinterpret_cast<const uint8_t *>(currentValue.Values.FloatValues);
unsigned int streamOffset; unsigned int streamOffset;
ANGLE_TRY(buffer.storeDynamicAttribute(context, attrib, binding, currentValue.Type, 0, 1, 0, ANGLE_TRY(buffer.storeDynamicAttribute(context, attrib, binding, currentValue.Type, 0, 1, 0,
&streamOffset, sourceData)); 0, &streamOffset, sourceData));
buffer.getVertexBuffer()->hintUnmapResource(); buffer.getVertexBuffer()->hintUnmapResource();
......
...@@ -111,7 +111,8 @@ class VertexDataManager : angle::NonCopyable ...@@ -111,7 +111,8 @@ class VertexDataManager : angle::NonCopyable
const gl::AttributesMask &dynamicAttribsMask, const gl::AttributesMask &dynamicAttribsMask,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances); GLsizei instances,
GLuint baseInstance);
// Promote static usage of dynamic buffers. // Promote static usage of dynamic buffers.
static void PromoteDynamicAttribs(const gl::Context *context, static void PromoteDynamicAttribs(const gl::Context *context,
...@@ -140,13 +141,15 @@ class VertexDataManager : angle::NonCopyable ...@@ -140,13 +141,15 @@ class VertexDataManager : angle::NonCopyable
const TranslatedAttribute &translatedAttrib, const TranslatedAttribute &translatedAttrib,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances); GLsizei instances,
GLuint baseInstance);
angle::Result storeDynamicAttrib(const gl::Context *context, angle::Result storeDynamicAttrib(const gl::Context *context,
TranslatedAttribute *translated, TranslatedAttribute *translated,
GLint start, GLint start,
size_t count, size_t count,
GLsizei instances); GLsizei instances,
GLuint baseInstance);
BufferFactoryD3D *const mFactory; BufferFactoryD3D *const mFactory;
......
...@@ -264,7 +264,7 @@ angle::Result Context11::drawArrays(const gl::Context *context, ...@@ -264,7 +264,7 @@ angle::Result Context11::drawArrays(const gl::Context *context,
{ {
ASSERT(count > 0); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0)); context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0));
return mRenderer->drawArrays(context, mode, first, count, 0, 0); return mRenderer->drawArrays(context, mode, first, count, 0, 0);
} }
...@@ -275,8 +275,9 @@ angle::Result Context11::drawArraysInstanced(const gl::Context *context, ...@@ -275,8 +275,9 @@ angle::Result Context11::drawArraysInstanced(const gl::Context *context,
GLsizei instanceCount) GLsizei instanceCount)
{ {
ASSERT(count > 0); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0)); gl::DrawElementsType::InvalidEnum, nullptr,
instanceCount, 0, 0));
return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0); return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0);
} }
...@@ -288,8 +289,9 @@ angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *cont ...@@ -288,8 +289,9 @@ angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *cont
GLuint baseInstance) GLuint baseInstance)
{ {
ASSERT(count > 0); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0)); gl::DrawElementsType::InvalidEnum, nullptr,
instanceCount, 0, baseInstance));
return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance); return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance);
} }
...@@ -312,15 +314,17 @@ ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *contex ...@@ -312,15 +314,17 @@ ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *contex
GLint startVertex; GLint startVertex;
ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex, ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex,
&startVertex)); &startVertex));
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, startVertex, indexCount,
context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex)); indexType, indices, instanceCount,
baseVertex, baseInstance));
return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices, return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices,
instanceCount, baseVertex, baseInstance); instanceCount, baseVertex, baseInstance);
} }
else else
{ {
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType, ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
indices, instanceCount, baseVertex)); indices, instanceCount, baseVertex,
baseInstance));
return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices, return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
instanceCount, baseVertex, baseInstance); instanceCount, baseVertex, baseInstance);
} }
...@@ -413,14 +417,14 @@ angle::Result Context11::drawArraysIndirect(const gl::Context *context, ...@@ -413,14 +417,14 @@ angle::Result Context11::drawArraysIndirect(const gl::Context *context,
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count, ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count,
gl::DrawElementsType::InvalidEnum, gl::DrawElementsType::InvalidEnum,
nullptr, cmd->instanceCount, 0)); nullptr, cmd->instanceCount, 0, 0));
return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount, return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
cmd->baseInstance); cmd->baseInstance);
} }
else else
{ {
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(
context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0)); context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0));
return mRenderer->drawArraysIndirect(context, indirect); return mRenderer->drawArraysIndirect(context, indirect);
} }
} }
...@@ -453,14 +457,14 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context, ...@@ -453,14 +457,14 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context,
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, startVertex, cmd->count, ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, startVertex, cmd->count,
type, indices, cmd->primCount, type, indices, cmd->primCount,
cmd->baseVertex)); cmd->baseVertex, cmd->baseInstance));
return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start), return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
cmd->count, type, indices, cmd->primCount, 0, 0); cmd->count, type, indices, cmd->primCount, 0, 0);
} }
else else
{ {
ANGLE_TRY( ANGLE_TRY(
mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0, 0)); mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0, 0, 0));
return mRenderer->drawElementsIndirect(context, indirect); return mRenderer->drawElementsIndirect(context, indirect);
} }
} }
......
...@@ -3843,6 +3843,7 @@ angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context, ...@@ -3843,6 +3843,7 @@ angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *bytesRequiredOut) const unsigned int *bytesRequiredOut) const
{ {
if (!attrib.enabled) if (!attrib.enabled)
...@@ -3861,7 +3862,8 @@ angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context, ...@@ -3861,7 +3862,8 @@ angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context,
else else
{ {
// Round up to divisor, if possible // Round up to divisor, if possible
elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor); elementCount =
UnsignedCeilDivide(static_cast<unsigned int>(instances + baseInstance), divisor);
} }
ASSERT(elementCount > 0); ASSERT(elementCount > 0);
......
...@@ -374,6 +374,7 @@ class Renderer11 : public RendererD3D ...@@ -374,6 +374,7 @@ class Renderer11 : public RendererD3D
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *bytesRequiredOut) const override; unsigned int *bytesRequiredOut) const override;
angle::Result readFromAttachment(const gl::Context *context, angle::Result readFromAttachment(const gl::Context *context,
......
...@@ -541,9 +541,10 @@ void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport, ...@@ -541,9 +541,10 @@ void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
} }
// Update the ShaderConstants with a new first vertex and return whether the update dirties them. // Update the ShaderConstants with a new first vertex and return whether the update dirties them.
ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex, GLint baseVertex) ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex)
{ {
uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex + baseVertex); // firstVertex should already include baseVertex, if any.
uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex);
bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex); bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex);
if (firstVertexDirty) if (firstVertexDirty)
...@@ -2167,7 +2168,8 @@ angle::Result StateManager11::updateState(const gl::Context *context, ...@@ -2167,7 +2168,8 @@ angle::Result StateManager11::updateState(const gl::Context *context,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
GLsizei instanceCount, GLsizei instanceCount,
GLint baseVertex) GLint baseVertex,
GLuint baseInstance)
{ {
const gl::State &glState = context->getState(); const gl::State &glState = context->getState();
...@@ -2211,7 +2213,7 @@ angle::Result StateManager11::updateState(const gl::Context *context, ...@@ -2211,7 +2213,7 @@ angle::Result StateManager11::updateState(const gl::Context *context,
ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount, ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
indexTypeOrInvalid, indices, instanceCount, indexTypeOrInvalid, indices, instanceCount,
baseVertex)); baseVertex, baseInstance));
// Changes in the draw call can affect the vertex buffer translations. // Changes in the draw call can affect the vertex buffer translations.
if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex) if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
...@@ -2223,7 +2225,18 @@ angle::Result StateManager11::updateState(const gl::Context *context, ...@@ -2223,7 +2225,18 @@ angle::Result StateManager11::updateState(const gl::Context *context,
// The ShaderConstants only need to be updated when the program uses vertexID // The ShaderConstants only need to be updated when the program uses vertexID
if (mProgramD3D->usesVertexID()) if (mProgramD3D->usesVertexID())
{ {
if (mShaderConstants.onFirstVertexChange(firstVertex, baseVertex)) GLint firstVertexOnChange = firstVertex + baseVertex;
ASSERT(mVertexArray11);
if (mVertexArray11->hasActiveDynamicAttrib(context) &&
indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
{
// drawElements with Dynamic attribute
// the firstVertex is already including baseVertex when
// doing ComputeStartVertex
firstVertexOnChange = firstVertex;
}
if (mShaderConstants.onFirstVertexChange(firstVertexOnChange))
{ {
mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
} }
......
...@@ -44,7 +44,7 @@ class ShaderConstants11 : angle::NonCopyable ...@@ -44,7 +44,7 @@ class ShaderConstants11 : angle::NonCopyable
const D3D11_VIEWPORT &dxViewport, const D3D11_VIEWPORT &dxViewport,
bool is9_3, bool is9_3,
bool presentPathFast); bool presentPathFast);
bool onFirstVertexChange(GLint firstVertex, GLint baseVertex); bool onFirstVertexChange(GLint firstVertex);
void onImageLayerChange(gl::ShaderType shaderType, unsigned int imageIndex, int layer); void onImageLayerChange(gl::ShaderType shaderType, unsigned int imageIndex, int layer);
void onSamplerChange(gl::ShaderType shaderType, void onSamplerChange(gl::ShaderType shaderType,
unsigned int samplerIndex, unsigned int samplerIndex,
...@@ -239,7 +239,8 @@ class StateManager11 final : angle::NonCopyable ...@@ -239,7 +239,8 @@ class StateManager11 final : angle::NonCopyable
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
GLsizei instanceCount, GLsizei instanceCount,
GLint baseVertex); GLint baseVertex,
GLuint baseInstance);
void setShaderResourceShared(gl::ShaderType shaderType, void setShaderResourceShared(gl::ShaderType shaderType,
UINT resourceSlot, UINT resourceSlot,
......
...@@ -127,7 +127,8 @@ angle::Result VertexArray11::syncStateForDraw(const gl::Context *context, ...@@ -127,7 +127,8 @@ angle::Result VertexArray11::syncStateForDraw(const gl::Context *context,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
GLsizei instances, GLsizei instances,
GLint baseVertex) GLint baseVertex,
GLuint baseInstance)
{ {
Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer(); Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
StateManager11 *stateManager = renderer->getStateManager(); StateManager11 *stateManager = renderer->getStateManager();
...@@ -159,7 +160,8 @@ angle::Result VertexArray11::syncStateForDraw(const gl::Context *context, ...@@ -159,7 +160,8 @@ angle::Result VertexArray11::syncStateForDraw(const gl::Context *context,
{ {
ANGLE_TRY(updateDynamicAttribs(context, stateManager->getVertexDataManager(), ANGLE_TRY(updateDynamicAttribs(context, stateManager->getVertexDataManager(),
firstVertex, vertexOrIndexCount, indexTypeOrInvalid, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
indices, instances, baseVertex, activeDynamicAttribs)); indices, instances, baseVertex, baseInstance,
activeDynamicAttribs));
stateManager->invalidateInputLayout(); stateManager->invalidateInputLayout();
} }
} }
...@@ -292,6 +294,7 @@ angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context, ...@@ -292,6 +294,7 @@ angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context,
const void *indices, const void *indices,
GLsizei instances, GLsizei instances,
GLint baseVertex, GLint baseVertex,
GLuint baseInstance,
const gl::AttributesMask &activeDynamicAttribs) const gl::AttributesMask &activeDynamicAttribs)
{ {
const auto &glState = context->getState(); const auto &glState = context->getState();
...@@ -315,8 +318,9 @@ angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context, ...@@ -315,8 +318,9 @@ angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context,
dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
} }
ANGLE_TRY(vertexDataManager->storeDynamicAttribs( ANGLE_TRY(vertexDataManager->storeDynamicAttribs(context, &mTranslatedAttribs,
context, &mTranslatedAttribs, activeDynamicAttribs, startVertex, vertexCount, instances)); activeDynamicAttribs, startVertex, vertexCount,
instances, baseInstance));
VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs, VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs,
vertexCount); vertexCount);
......
...@@ -39,7 +39,8 @@ class VertexArray11 : public VertexArrayImpl ...@@ -39,7 +39,8 @@ class VertexArray11 : public VertexArrayImpl
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
GLsizei instances, GLsizei instances,
GLint baseVertex); GLint baseVertex,
GLuint baseInstance);
// This will check the dynamic attribs mask. // This will check the dynamic attribs mask.
bool hasActiveDynamicAttrib(const gl::Context *context); bool hasActiveDynamicAttrib(const gl::Context *context);
...@@ -72,6 +73,7 @@ class VertexArray11 : public VertexArrayImpl ...@@ -72,6 +73,7 @@ class VertexArray11 : public VertexArrayImpl
const void *indices, const void *indices,
GLsizei instances, GLsizei instances,
GLint baseVertex, GLint baseVertex,
GLuint baseInstance,
const gl::AttributesMask &activeDynamicAttribs); const gl::AttributesMask &activeDynamicAttribs);
angle::Result updateElementArrayStorage(const gl::Context *context, angle::Result updateElementArrayStorage(const gl::Context *context,
......
...@@ -2976,6 +2976,7 @@ angle::Result Renderer9::getVertexSpaceRequired(const gl::Context *context, ...@@ -2976,6 +2976,7 @@ angle::Result Renderer9::getVertexSpaceRequired(const gl::Context *context,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *bytesRequiredOut) const unsigned int *bytesRequiredOut) const
{ {
if (!attrib.enabled) if (!attrib.enabled)
......
...@@ -374,6 +374,7 @@ class Renderer9 : public RendererD3D ...@@ -374,6 +374,7 @@ class Renderer9 : public RendererD3D
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t count, size_t count,
GLsizei instances, GLsizei instances,
GLuint baseInstance,
unsigned int *bytesRequiredOut) const override; unsigned int *bytesRequiredOut) const override;
angle::Result copyToRenderTarget(const gl::Context *context, angle::Result copyToRenderTarget(const gl::Context *context,
......
...@@ -78,7 +78,7 @@ angle::Result VertexBuffer9::storeVertexAttributes(const gl::Context *context, ...@@ -78,7 +78,7 @@ angle::Result VertexBuffer9::storeVertexAttributes(const gl::Context *context,
unsigned int mapSize = 0; unsigned int mapSize = 0;
ANGLE_TRY( ANGLE_TRY(
mRenderer->getVertexSpaceRequired(context, attrib, binding, count, instances, &mapSize)); mRenderer->getVertexSpaceRequired(context, attrib, binding, count, instances, 0, &mapSize));
HRESULT result = HRESULT result =
mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void **>(&mapPtr), lockFlags); mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void **>(&mapPtr), lockFlags);
......
...@@ -63,8 +63,14 @@ enum class BaseInstanceOption ...@@ -63,8 +63,14 @@ enum class BaseInstanceOption
UseBaseInstance UseBaseInstance
}; };
using DrawBaseVertexBaseInstanceTestParams = enum class BufferDataUsageOption
std::tuple<angle::PlatformParameters, BaseVertexOption, BaseInstanceOption>; {
StaticDraw,
DynamicDraw
};
using DrawBaseVertexBaseInstanceTestParams = std::
tuple<angle::PlatformParameters, BaseVertexOption, BaseInstanceOption, BufferDataUsageOption>;
struct PrintToStringParamName struct PrintToStringParamName
{ {
...@@ -72,7 +78,9 @@ struct PrintToStringParamName ...@@ -72,7 +78,9 @@ struct PrintToStringParamName
const ::testing::TestParamInfo<DrawBaseVertexBaseInstanceTestParams> &info) const const ::testing::TestParamInfo<DrawBaseVertexBaseInstanceTestParams> &info) const
{ {
::std::stringstream ss; ::std::stringstream ss;
ss << (std::get<2>(info.param) == BaseInstanceOption::UseBaseInstance ? "UseBaseInstance_" ss << (std::get<3>(info.param) == BufferDataUsageOption::StaticDraw ? "StaticDraw_"
: "DynamicDraw_")
<< (std::get<2>(info.param) == BaseInstanceOption::UseBaseInstance ? "UseBaseInstance_"
: "") : "")
<< (std::get<1>(info.param) == BaseVertexOption::UseBaseVertex ? "UseBaseVertex_" : "") << (std::get<1>(info.param) == BaseVertexOption::UseBaseVertex ? "UseBaseVertex_" : "")
<< std::get<0>(info.param); << std::get<0>(info.param);
...@@ -151,6 +159,12 @@ class DrawBaseVertexBaseInstanceTest ...@@ -151,6 +159,12 @@ class DrawBaseVertexBaseInstanceTest
return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance; return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance;
} }
GLenum getBufferDataUsage() const
{
return std::get<3>(GetParam()) == BufferDataUsageOption::StaticDraw ? GL_STATIC_DRAW
: GL_DYNAMIC_DRAW;
}
std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw, bool divisorTest) std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw, bool divisorTest)
{ {
// Each color channel is to test the value of // Each color channel is to test the value of
...@@ -179,8 +193,8 @@ void main() ...@@ -179,8 +193,8 @@ void main()
<< "float x_color = " << "float x_color = "
<< (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;") << (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;")
<< R"( << R"(
float y_id = floor(float(gl_VertexID) / )" float y_id = float(gl_VertexID / )"
<< (isDrawArrays ? "6.0" : "4.0") << R"( + 0.01); << (isDrawArrays ? "6" : "4") << R"();
color = vec4( color = vec4(
x_color, x_color,
...@@ -233,7 +247,7 @@ void main() ...@@ -233,7 +247,7 @@ void main()
{ {
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get()); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(), glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
mNonIndexedVertices.data(), GL_STATIC_DRAW); mNonIndexedVertices.data(), getBufferDataUsage());
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
...@@ -242,11 +256,11 @@ void main() ...@@ -242,11 +256,11 @@ void main()
{ {
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(), glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
GL_STATIC_DRAW); getBufferDataUsage());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(), glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
GL_STATIC_DRAW); getBufferDataUsage());
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
...@@ -255,7 +269,7 @@ void main() ...@@ -255,7 +269,7 @@ void main()
{ {
glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer); glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(), glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(),
mInstancedArrayId.data(), GL_STATIC_DRAW); mInstancedArrayId.data(), getBufferDataUsage());
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
...@@ -264,7 +278,7 @@ void main() ...@@ -264,7 +278,7 @@ void main()
{ {
glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer); glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(), glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(),
mInstancedArrayColorId.data(), GL_STATIC_DRAW); mInstancedArrayColorId.data(), getBufferDataUsage());
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
...@@ -273,7 +287,7 @@ void main() ...@@ -273,7 +287,7 @@ void main()
{ {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mRegularIndices.size(), glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mRegularIndices.size(),
mRegularIndices.data(), GL_STATIC_DRAW); mRegularIndices.data(), getBufferDataUsage());
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
...@@ -584,6 +598,7 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance) ...@@ -584,6 +598,7 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
} }
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
ANGLE_SKIP_TEST_IF(getBufferDataUsage() == GL_DYNAMIC_DRAW);
GLProgram program; GLProgram program;
setupProgram(program, true, true); setupProgram(program, true, true);
...@@ -641,6 +656,7 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstan ...@@ -641,6 +656,7 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstan
TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance) TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
{ {
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
ANGLE_SKIP_TEST_IF(getBufferDataUsage() == GL_DYNAMIC_DRAW);
GLProgram program; GLProgram program;
setupProgram(program, false, true); setupProgram(program, false, true);
...@@ -680,7 +696,8 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -680,7 +696,8 @@ INSTANTIATE_TEST_SUITE_P(
testing::Combine( testing::Combine(
testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))), testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex), testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance)), testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance),
testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw)),
PrintToStringParamName()); PrintToStringParamName());
} // namespace } // namespace
...@@ -56,12 +56,13 @@ class MockBufferFactoryD3D : public rx::BufferFactoryD3D ...@@ -56,12 +56,13 @@ class MockBufferFactoryD3D : public rx::BufferFactoryD3D
MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *()); MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *());
MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(angle::FormatID)); MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(angle::FormatID));
MOCK_CONST_METHOD1(getVertexComponentType, GLenum(angle::FormatID)); MOCK_CONST_METHOD1(getVertexComponentType, GLenum(angle::FormatID));
MOCK_CONST_METHOD6(getVertexSpaceRequired, MOCK_CONST_METHOD7(getVertexSpaceRequired,
angle::Result(const gl::Context *, angle::Result(const gl::Context *,
const gl::VertexAttribute &, const gl::VertexAttribute &,
const gl::VertexBinding &, const gl::VertexBinding &,
size_t, size_t,
GLsizei, GLsizei,
GLuint,
unsigned int *)); unsigned int *));
// Dependency injection // Dependency injection
......
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