Commit 4dd1e55f by Jamie Madill

D3D11: Implement basic primitive restart.

D3D11 handles primitive restart similarly to OpenGL's fixed index, with a couple differences. It can't be toggled off, so we need to restrict the max element index (handled in a prior patch), and for smaller buffer types we need to rewrite the index data. BUG=angleproject:597 Change-Id: Ib890ce9b3f5511784138ea3953a384b1c483ca9e Reviewed-on: https://chromium-review.googlesource.com/309639Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c4c74422
...@@ -18,48 +18,73 @@ ...@@ -18,48 +18,73 @@
namespace rx namespace rx
{ {
static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, namespace
GLsizei count, void *output)
{ {
if (sourceType == GL_UNSIGNED_BYTE)
{
ASSERT(destinationType == GL_UNSIGNED_SHORT);
const GLubyte *in = static_cast<const GLubyte*>(input);
GLushort *out = static_cast<GLushort*>(output);
template <typename InputT, typename DestT>
void ConvertIndexArray(const void *input,
GLenum sourceType,
void *output,
GLenum destinationType,
GLsizei count,
bool usePrimitiveRestartFixedIndex)
{
const InputT *in = static_cast<const InputT *>(input);
DestT *out = static_cast<DestT *>(output);
if (usePrimitiveRestartFixedIndex)
{
InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType));
DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType));
for (GLsizei i = 0; i < count; i++) for (GLsizei i = 0; i < count; i++)
{ {
out[i] = in[i]; out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i]));
}
} }
else if (sourceType == GL_UNSIGNED_INT)
{
ASSERT(destinationType == GL_UNSIGNED_INT);
memcpy(output, input, count * sizeof(GLuint));
} }
else if (sourceType == GL_UNSIGNED_SHORT) else
{ {
if (destinationType == GL_UNSIGNED_SHORT) for (GLsizei i = 0; i < count; i++)
{ {
memcpy(output, input, count * sizeof(GLushort)); out[i] = static_cast<DestT>(in[i]);
} }
else if (destinationType == GL_UNSIGNED_INT) }
{ }
const GLushort *in = static_cast<const GLushort*>(input);
GLuint *out = static_cast<GLuint*>(output);
for (GLsizei i = 0; i < count; i++) void ConvertIndices(GLenum sourceType,
GLenum destinationType,
const void *input,
GLsizei count,
void *output,
bool usePrimitiveRestartFixedIndex)
{
if (sourceType == destinationType)
{ {
out[i] = in[i]; const gl::Type &typeInfo = gl::GetTypeInfo(destinationType);
memcpy(output, input, count * typeInfo.bytes);
return;
} }
if (sourceType == GL_UNSIGNED_BYTE)
{
ASSERT(destinationType == GL_UNSIGNED_SHORT);
ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
usePrimitiveRestartFixedIndex);
} }
else UNREACHABLE(); else if (sourceType == GL_UNSIGNED_SHORT)
{
ASSERT(destinationType == GL_UNSIGNED_INT);
ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
usePrimitiveRestartFixedIndex);
} }
else UNREACHABLE(); else UNREACHABLE();
} }
static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid *data, gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
unsigned int count, GLenum srcType, GLenum dstType, const GLvoid *data,
unsigned int count,
GLenum srcType,
GLenum dstType,
bool usePrimitiveRestartFixedIndex,
unsigned int *offset) unsigned int *offset)
{ {
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
...@@ -85,7 +110,7 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid ...@@ -85,7 +110,7 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid
return error; return error;
} }
ConvertIndices(srcType, dstType, data, count, output); ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
error = buffer->unmapBuffer(); error = buffer->unmapBuffer();
if (error.isError()) if (error.isError())
...@@ -96,6 +121,8 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid ...@@ -96,6 +121,8 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
} // anonymous namespace
IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
: mFactory(factory), : mFactory(factory),
mRendererClass(rendererClass), mRendererClass(rendererClass),
...@@ -118,9 +145,13 @@ IndexDataManager::~IndexDataManager() ...@@ -118,9 +145,13 @@ IndexDataManager::~IndexDataManager()
// When we have a buffer with an unsupported format (subcase b) then we need to do some translation: // When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
// we will start by falling back to streaming, and after a while will start using a static translated // we will start by falling back to streaming, and after a while will start using a static translated
// copy of the index buffer. // copy of the index buffer.
gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer, gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
const GLvoid *indices, TranslatedIndexData *translated, GLsizei count,
SourceIndexData *sourceData) gl::Buffer *glBuffer,
const GLvoid *indices,
TranslatedIndexData *translated,
SourceIndexData *sourceData,
bool primitiveRestartFixedIndexEnabled)
{ {
// Avoid D3D11's primitive restart index value // Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
...@@ -128,8 +159,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -128,8 +159,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
translated->indexRange.vertexIndexCount < static_cast<size_t>(count) || translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType); translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 && bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 &&
!primitiveRestartFixedIndexEnabled &&
hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT; hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT;
// We should never have to deal with MAX_UINT indices, since we restrict it via
// MAX_ELEMENT_INDEX.
ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT));
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ? const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ?
GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
...@@ -151,7 +188,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -151,7 +188,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
if (glBuffer == nullptr) if (glBuffer == nullptr)
{ {
translated->storage = nullptr; translated->storage = nullptr;
return streamIndexData(indices, count, srcType, dstType, translated); return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled,
translated);
} }
// Case 2: the indices are already in a buffer // Case 2: the indices are already in a buffer
...@@ -207,7 +245,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -207,7 +245,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
} }
ASSERT(bufferData != nullptr); ASSERT(bufferData != nullptr);
error = streamIndexData(bufferData + offset, count, srcType, dstType, translated); error = streamIndexData(bufferData + offset, count, srcType, dstType,
primitiveRestartFixedIndexEnabled, translated);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -227,8 +266,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -227,8 +266,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
unsigned int convertCount = unsigned int convertCount =
static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift; static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift;
error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
srcType, dstType, nullptr); primitiveRestartFixedIndexEnabled, nullptr);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -245,8 +284,12 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -245,8 +284,12 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType, gl::Error IndexDataManager::streamIndexData(const GLvoid *data,
GLenum dstType, TranslatedIndexData *translated) unsigned int count,
GLenum srcType,
GLenum dstType,
bool usePrimitiveRestartFixedIndex,
TranslatedIndexData *translated)
{ {
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
...@@ -259,7 +302,8 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int cou ...@@ -259,7 +302,8 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int cou
ASSERT(indexBuffer != nullptr); ASSERT(indexBuffer != nullptr);
unsigned int offset; unsigned int offset;
StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, &offset); StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex,
&offset);
translated->indexBuffer = indexBuffer->getIndexBuffer(); translated->indexBuffer = indexBuffer->getIndexBuffer();
translated->serial = indexBuffer->getSerial(); translated->serial = indexBuffer->getSerial();
......
...@@ -63,13 +63,21 @@ class IndexDataManager : angle::NonCopyable ...@@ -63,13 +63,21 @@ class IndexDataManager : angle::NonCopyable
explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
virtual ~IndexDataManager(); virtual ~IndexDataManager();
gl::Error prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer, gl::Error prepareIndexData(GLenum srcType,
const GLvoid *indices, TranslatedIndexData *translated, GLsizei count,
SourceIndexData *sourceData); gl::Buffer *glBuffer,
const GLvoid *indices,
TranslatedIndexData *translated,
SourceIndexData *sourceData,
bool primitiveRestartFixedIndexEnabled);
private: private:
gl::Error streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType, gl::Error streamIndexData(const GLvoid *data,
GLenum dstType, TranslatedIndexData *translated); unsigned int count,
GLenum srcType,
GLenum dstType,
bool usePrimitiveRestartFixedIndex,
TranslatedIndexData *translated);
gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, gl::Error getStreamingIndexBuffer(GLenum destinationIndexType,
IndexBufferInterface **outBuffer); IndexBufferInterface **outBuffer);
......
...@@ -134,12 +134,6 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, ...@@ -134,12 +134,6 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
GLsizei instances, GLsizei instances,
const gl::IndexRange &indexRange) const gl::IndexRange &indexRange)
{ {
if (data.state->isPrimitiveRestartEnabled())
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented");
}
gl::Program *program = data.state->getProgram(); gl::Program *program = data.state->getProgram();
ASSERT(program != nullptr); ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
...@@ -170,13 +164,12 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, ...@@ -170,13 +164,12 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
return error; return error;
} }
gl::VertexArray *vao = data.state->getVertexArray();
TranslatedIndexData indexInfo; TranslatedIndexData indexInfo;
indexInfo.indexRange = indexRange; indexInfo.indexRange = indexRange;
SourceIndexData sourceIndexInfo; SourceIndexData sourceIndexInfo;
error = applyIndexBuffer(indices, vao->getElementArrayBuffer().get(), count, mode, type, &indexInfo, &sourceIndexInfo); error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo, &sourceIndexInfo);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -215,8 +208,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data, ...@@ -215,8 +208,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
if (!skipDraw(data, mode)) if (!skipDraw(data, mode))
{ {
error = drawElementsImpl(mode, count, type, indices, vao->getElementArrayBuffer().get(), error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances);
indexInfo, instances, usesPointSize);
if (error.isError()) if (error.isError())
{ {
return error; return error;
......
...@@ -165,7 +165,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -165,7 +165,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
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, SourceIndexData *sourceIndexInfo) = 0;
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) = 0; virtual gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices,
GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo,
SourceIndexData *sourceIndexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
virtual void markAllStateDirty() = 0; virtual void markAllStateDirty() = 0;
...@@ -279,14 +285,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -279,14 +285,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
GLsizei instances) = 0; GLsizei instances) = 0;
virtual gl::Error drawElementsImpl(GLenum mode, virtual gl::Error drawElementsImpl(const gl::Data &data,
const TranslatedIndexData &indexInfo,
GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, GLsizei instances) = 0;
const TranslatedIndexData &indexInfo,
GLsizei instances,
bool usesPointSize) = 0;
//FIXME(jmadill): std::array is currently prohibited by Chromium style guide //FIXME(jmadill): std::array is currently prohibited by Chromium style guide
typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray; typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
......
...@@ -194,8 +194,51 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) ...@@ -194,8 +194,51 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
} }
} }
void SetLineLoopIndices(GLuint *dest, size_t count)
{
for (size_t i = 0; i < count; i++)
{
dest[i] = static_cast<GLuint>(i);
}
dest[count] = 0;
}
template <typename T>
void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count)
{
const T *srcPtr = static_cast<const T *>(indices);
for (size_t i = 0; i < count; ++i)
{
dest[i] = static_cast<GLuint>(srcPtr[i]);
}
dest[count] = static_cast<GLuint>(srcPtr[0]);
}
void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
{
for (size_t i = 0; i < numTris; i++)
{
destPtr[i * 3 + 0] = 0;
destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
}
}
template <typename T>
void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris)
{
const T *srcPtr = static_cast<const T *>(indices);
for (size_t i = 0; i < numTris; i++)
{
destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
}
} }
} // anonymous namespace
void Renderer11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) void Renderer11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
{ {
ASSERT(resourceIndex < mCurrentSRVs.size()); ASSERT(resourceIndex < mCurrentSRVs.size());
...@@ -1573,9 +1616,19 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi ...@@ -1573,9 +1616,19 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi
return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), sourceInfo); return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), sourceInfo);
} }
gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
{ const GLvoid *indices,
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo); GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo,
SourceIndexData *sourceIndexInfo)
{
gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
indexInfo, sourceIndexInfo,
data.state->isPrimitiveRestartEnabled());
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -1738,12 +1791,12 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, ...@@ -1738,12 +1791,12 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
if (mode == GL_LINE_LOOP) if (mode == GL_LINE_LOOP)
{ {
return drawLineLoop(count, GL_NONE, NULL, 0, NULL); return drawLineLoop(data, count, GL_NONE, nullptr, 0);
} }
if (mode == GL_TRIANGLE_FAN) if (mode == GL_TRIANGLE_FAN)
{ {
return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
} }
if (instances > 0) if (instances > 0)
...@@ -1769,37 +1822,37 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, ...@@ -1769,37 +1822,37 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
gl::Error Renderer11::drawElementsImpl(GLenum mode, gl::Error Renderer11::drawElementsImpl(const gl::Data &data,
const TranslatedIndexData &indexInfo,
GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, GLsizei instances)
const TranslatedIndexData &indexInfo,
GLsizei instances,
bool usesPointSize)
{ {
bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
int minIndex = static_cast<int>(indexInfo.indexRange.start); int minIndex = static_cast<int>(indexInfo.indexRange.start);
if (mode == GL_LINE_LOOP) if (mode == GL_LINE_LOOP)
{ {
return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); return drawLineLoop(data, count, type, indices, minIndex);
} }
else if (mode == GL_TRIANGLE_FAN)
if (mode == GL_TRIANGLE_FAN)
{ {
return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); return drawTriangleFan(data, count, type, indices, minIndex, instances);
} }
else if (instances > 0)
if (instances > 0)
{ {
mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
else
{
// 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.
if (mode == GL_POINTS && useInstancedPointSpriteEmulation) const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
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
// to be rendered. Each instance is referenced by the bound index buffer from the // to be rendered. Each instance is referenced by the bound index buffer from the
...@@ -1810,18 +1863,23 @@ gl::Error Renderer11::drawElementsImpl(GLenum mode, ...@@ -1810,18 +1863,23 @@ gl::Error Renderer11::drawElementsImpl(GLenum mode,
// This is not an efficent rendering mechanism and is only used on downlevel renderers // This is not an efficent rendering mechanism and is only used on downlevel renderers
// that do not support geometry shaders. // that do not support geometry shaders.
mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
return gl::Error(GL_NO_ERROR);
} }
else else
{ {
mDeviceContext->DrawIndexed(count, 0, -minIndex); mDeviceContext->DrawIndexed(count, 0, -minIndex);
return gl::Error(GL_NO_ERROR);
}
} }
return gl::Error(GL_NO_ERROR);
} }
gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) gl::Error Renderer11::drawLineLoop(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
int minIndex)
{ {
gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
// Get the raw indices for an indexed draw // Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer) if (type != GL_NONE && elementArrayBuffer)
{ {
...@@ -1872,40 +1930,34 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind ...@@ -1872,40 +1930,34 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
return error; return error;
} }
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); unsigned int *mappedInts = reinterpret_cast<unsigned int *>(mappedMemory);
unsigned int indexBufferOffset = offset; unsigned int indexBufferOffset = offset;
switch (type) if (type != GL_NONE && data.state->isPrimitiveRestartEnabled())
{
case GL_NONE: // Non-indexed draw
for (int i = 0; i < count; i++)
{ {
data[i] = i; // TODO(jmadill): Implement this.
return gl::Error(GL_INVALID_OPERATION,
"Primitive restart not yet supported for line loops.");
} }
data[count] = 0;
// Non-indexed draw
switch (type)
{
case GL_NONE:
SetLineLoopIndices(mappedInts, count);
break; break;
case GL_UNSIGNED_BYTE: case GL_UNSIGNED_BYTE:
for (int i = 0; i < count; i++) CopyLineLoopIndices<GLubyte>(indices, mappedInts, count);
{
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break; break;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++) CopyLineLoopIndices<GLushort>(indices, mappedInts, count);
{
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break; break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++) CopyLineLoopIndices<GLuint>(indices, mappedInts, count);
{ break;
data[i] = static_cast<const GLuint*>(indices)[i]; default:
} UNREACHABLE();
data[count] = static_cast<const GLuint*>(indices)[0];
break; break;
default: UNREACHABLE();
} }
error = mLineLoopIB->unmapBuffer(); error = mLineLoopIB->unmapBuffer();
...@@ -1931,8 +1983,16 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind ...@@ -1931,8 +1983,16 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) gl::Error Renderer11::drawTriangleFan(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
int minIndex,
int instances)
{ {
gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
// Get the raw indices for an indexed draw // Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer) if (type != GL_NONE && elementArrayBuffer)
{ {
...@@ -1985,44 +2045,34 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * ...@@ -1985,44 +2045,34 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return error; return error;
} }
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); unsigned int *destPtr = reinterpret_cast<unsigned int *>(mappedMemory);
unsigned int indexBufferOffset = offset; unsigned int indexBufferOffset = offset;
switch (type) // Non-indexed draw
{ if (type != GL_NONE && data.state->isPrimitiveRestartEnabled())
case GL_NONE: // Non-indexed draw
for (unsigned int i = 0; i < numTris; i++)
{ {
data[i*3 + 0] = 0; // TODO(jmadill): Implement this.
data[i*3 + 1] = i + 1; return gl::Error(GL_INVALID_OPERATION,
data[i*3 + 2] = i + 2; "Primitive restart not yet supported for triangle fans.");
} }
switch (type)
{
case GL_NONE:
SetTriangleFanIndices(destPtr, numTris);
break; break;
case GL_UNSIGNED_BYTE: case GL_UNSIGNED_BYTE:
for (unsigned int i = 0; i < numTris; i++) CopyTriangleFanIndices<GLubyte>(indices, destPtr, numTris);
{
data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
}
break; break;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
for (unsigned int i = 0; i < numTris; i++) CopyTriangleFanIndices<GLushort>(indices, destPtr, numTris);
{
data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
}
break; break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
for (unsigned int i = 0; i < numTris; i++) CopyTriangleFanIndices<GLuint>(indices, destPtr, numTris);
{ break;
data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; default:
data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; UNREACHABLE();
data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
}
break; break;
default: UNREACHABLE();
} }
error = mTriangleFanIB->unmapBuffer(); error = mTriangleFanIB->unmapBuffer();
......
...@@ -136,7 +136,13 @@ class Renderer11 : public RendererD3D ...@@ -136,7 +136,13 @@ class Renderer11 : public RendererD3D
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, SourceIndexData *sourceIndexInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo); gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices,
GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo,
SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override; void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual void markAllStateDirty(); virtual void markAllStateDirty();
...@@ -276,14 +282,13 @@ class Renderer11 : public RendererD3D ...@@ -276,14 +282,13 @@ class Renderer11 : public RendererD3D
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
GLsizei instances) override; GLsizei instances) override;
gl::Error drawElementsImpl(GLenum mode, gl::Error drawElementsImpl(const gl::Data &data,
const TranslatedIndexData &indexInfo,
GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, GLsizei instances) override;
const TranslatedIndexData &indexInfo,
GLsizei instances,
bool usesPointSize) override;
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions, gl::Extensions *outExtensions,
...@@ -291,8 +296,17 @@ class Renderer11 : public RendererD3D ...@@ -291,8 +296,17 @@ class Renderer11 : public RendererD3D
WorkaroundsD3D generateWorkarounds() const override; WorkaroundsD3D generateWorkarounds() const override;
gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); gl::Error drawLineLoop(const gl::Data &data,
gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); GLsizei count,
GLenum type,
const GLvoid *indices,
int minIndex);
gl::Error drawTriangleFan(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
int minIndex,
int instances);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex &index); void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex &index);
......
...@@ -1455,9 +1455,18 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLin ...@@ -1455,9 +1455,18 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLin
} }
// Applies the indices and element array bindings to the Direct3D 9 device // Applies the indices and element array bindings to the Direct3D 9 device
gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) gl::Error Renderer9::applyIndexBuffer(const gl::Data &data,
const GLvoid *indices,
GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo,
SourceIndexData *sourceIndexInfo)
{ {
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo); gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
indexInfo, sourceIndexInfo, false);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -1526,19 +1535,21 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data, ...@@ -1526,19 +1535,21 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
} }
} }
gl::Error Renderer9::drawElementsImpl(GLenum mode, gl::Error Renderer9::drawElementsImpl(const gl::Data &data,
const TranslatedIndexData &indexInfo,
GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, GLsizei /*instances*/)
const TranslatedIndexData &indexInfo,
GLsizei /*instances*/,
bool /*usesPointSize*/)
{ {
startScene(); startScene();
int minIndex = static_cast<int>(indexInfo.indexRange.start); int minIndex = static_cast<int>(indexInfo.indexRange.start);
gl::VertexArray *vao = data.state->getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
if (mode == GL_POINTS) if (mode == GL_POINTS)
{ {
return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
......
...@@ -114,7 +114,13 @@ class Renderer9 : public RendererD3D ...@@ -114,7 +114,13 @@ class Renderer9 : public RendererD3D
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, SourceIndexData *sourceInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo); gl::Error applyIndexBuffer(const gl::Data &data,
const GLvoid *indices,
GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo,
SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override; void applyTransformFeedbackBuffers(const gl::State &state) override;
...@@ -243,14 +249,13 @@ class Renderer9 : public RendererD3D ...@@ -243,14 +249,13 @@ class Renderer9 : public RendererD3D
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
GLsizei instances) override; GLsizei instances) override;
gl::Error drawElementsImpl(GLenum mode, gl::Error drawElementsImpl(const gl::Data &data,
const TranslatedIndexData &indexInfo,
GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, GLsizei instances) override;
const TranslatedIndexData &indexInfo,
GLsizei instances,
bool usesPointSize) override;
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions, gl::Extensions *outExtensions,
......
...@@ -159,7 +159,8 @@ void IndexDataManagerPerfTest::step(float dt, double totalTime) ...@@ -159,7 +159,8 @@ void IndexDataManagerPerfTest::step(float dt, double totalTime)
{ {
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, &translatedIndexData, &sourceIndexData); mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr,
&translatedIndexData, &sourceIndexData, false);
} }
if (mTimer->getElapsedTime() >= 5.0) if (mTimer->getElapsedTime() >= 5.0)
......
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