Commit b78ea276 by Nicolas Capens

Avoid D3D11 primitive restart index using 32-bit indices

D3D11 interprets an index value of 0xFFFF in a 16-bit index buffer as a primitive restart marker. This behavior can't be toggled off. http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx We work around it by converting to 32-bit indices. BUG=angle:708 Change-Id: Ibc92d6ba98e5f11a98d76cae14f90ca050a19964
parent 07d49ef5
#include "precompiled.h" #include "precompiled.h"
// //
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "libGLESv2/main.h" #include "libGLESv2/main.h"
#include "libGLESv2/formatutils.h" #include "libGLESv2/formatutils.h"
#include "libGLESv2/renderer/d3d/IndexBuffer.h" #include "libGLESv2/renderer/d3d/IndexBuffer.h"
#include "libGLESv2/renderer/Renderer.h"
namespace rx namespace rx
{ {
...@@ -54,10 +55,11 @@ IndexDataManager::~IndexDataManager() ...@@ -54,10 +55,11 @@ IndexDataManager::~IndexDataManager()
delete mCountingBuffer; delete mCountingBuffer;
} }
static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) static void convertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output)
{ {
if (type == GL_UNSIGNED_BYTE) if (sourceType == GL_UNSIGNED_BYTE)
{ {
ASSERT(destinationType == GL_UNSIGNED_SHORT);
const GLubyte *in = static_cast<const GLubyte*>(input); const GLubyte *in = static_cast<const GLubyte*>(input);
GLushort *out = static_cast<GLushort*>(output); GLushort *out = static_cast<GLushort*>(output);
...@@ -66,14 +68,29 @@ static void convertIndices(GLenum type, const void *input, GLsizei count, void * ...@@ -66,14 +68,29 @@ static void convertIndices(GLenum type, const void *input, GLsizei count, void *
out[i] = in[i]; out[i] = in[i];
} }
} }
else if (type == GL_UNSIGNED_INT) else if (sourceType == GL_UNSIGNED_INT)
{ {
ASSERT(destinationType == GL_UNSIGNED_INT);
memcpy(output, input, count * sizeof(GLuint)); memcpy(output, input, count * sizeof(GLuint));
} }
else if (type == GL_UNSIGNED_SHORT) else if (sourceType == GL_UNSIGNED_SHORT)
{
if (destinationType == GL_UNSIGNED_SHORT)
{ {
memcpy(output, input, count * sizeof(GLushort)); memcpy(output, input, count * sizeof(GLushort));
} }
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++)
{
out[i] = in[i];
}
}
else UNREACHABLE();
}
else UNREACHABLE(); else UNREACHABLE();
} }
...@@ -155,17 +172,14 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -155,17 +172,14 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
indices = static_cast<const GLubyte*>(storage->getData()) + offset; indices = static_cast<const GLubyte*>(storage->getData()) + offset;
} }
StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL;
IndexBufferInterface *indexBuffer = streamingBuffer; IndexBufferInterface *indexBuffer = NULL;
bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
destinationIndexType == type; destinationIndexType == type;
unsigned int streamOffset = 0; unsigned int streamOffset = 0;
if (directStorage) if (directStorage)
{ {
indexBuffer = streamingBuffer;
streamOffset = offset; streamOffset = offset;
if (!storage->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, if (!storage->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
...@@ -191,6 +205,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -191,6 +205,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
} }
else else
{ {
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
}
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
if (translated->maxIndex == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3)
{
destinationIndexType = GL_UNSIGNED_INT;
directStorage = false;
indexBuffer = NULL;
}
if (!directStorage && !indexBuffer)
{
indexBuffer = (destinationIndexType == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
unsigned int convertCount = count; unsigned int convertCount = count;
if (staticBuffer) if (staticBuffer)
...@@ -234,7 +264,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -234,7 +264,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
return GL_OUT_OF_MEMORY; return GL_OUT_OF_MEMORY;
} }
convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); convertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output);
if (!indexBuffer->unmapBuffer()) if (!indexBuffer->unmapBuffer())
{ {
...@@ -242,8 +272,6 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -242,8 +272,6 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
return GL_OUT_OF_MEMORY; return GL_OUT_OF_MEMORY;
} }
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
if (staticBuffer) if (staticBuffer)
{ {
streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType);
...@@ -253,10 +281,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -253,10 +281,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
} }
translated->storage = directStorage ? storage : NULL; translated->storage = directStorage ? storage : NULL;
translated->indexBuffer = indexBuffer->getIndexBuffer(); translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL;
translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType);
translated->startOffset = streamOffset; translated->startOffset = streamOffset;
translated->indexType = destinationIndexType;
if (storage) if (storage)
{ {
......
// //
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -39,6 +39,7 @@ struct TranslatedIndexData ...@@ -39,6 +39,7 @@ struct TranslatedIndexData
IndexBuffer *indexBuffer; IndexBuffer *indexBuffer;
BufferD3D *storage; BufferD3D *storage;
GLenum indexType;
unsigned int serial; unsigned int serial;
}; };
......
...@@ -968,10 +968,8 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr ...@@ -968,10 +968,8 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr
if (err == GL_NO_ERROR) if (err == GL_NO_ERROR)
{ {
IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
ID3D11Buffer *buffer = NULL; ID3D11Buffer *buffer = NULL;
DXGI_FORMAT bufferFormat = indexBuffer->getIndexFormat(); DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
if (indexInfo->storage) if (indexInfo->storage)
{ {
...@@ -980,6 +978,7 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr ...@@ -980,6 +978,7 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr
} }
else else
{ {
IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
buffer = indexBuffer->getBuffer(); buffer = indexBuffer->getBuffer();
} }
...@@ -1203,7 +1202,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, ...@@ -1203,7 +1202,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
{ {
mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
mAppliedIB = d3dIndexBuffer; mAppliedIB = d3dIndexBuffer;
mAppliedIBFormat = indexFormat; mAppliedIBFormat = indexFormat;
mAppliedIBOffset = indexBufferOffset; mAppliedIBOffset = indexBufferOffset;
...@@ -1314,7 +1313,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic ...@@ -1314,7 +1313,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
{ {
mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
mAppliedIB = d3dIndexBuffer; mAppliedIB = d3dIndexBuffer;
mAppliedIBFormat = indexFormat; mAppliedIBFormat = indexFormat;
mAppliedIBOffset = indexBufferOffset; mAppliedIBOffset = indexBufferOffset;
......
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