Commit 578b51fd by Jamie Madill Committed by Commit Bot

D3D: Add helper for index translation type.

This makes it a bit simpler to work with the prepareIndexData method. Also removes the mRendererClass member of the index data manager since it was no longer necessary. BUG=angleproject:2229 Change-Id: I03768b104da21f57c499239bbbb5f716efb0fd48 Reviewed-on: https://chromium-review.googlesource.com/765261 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 92019431
...@@ -112,11 +112,8 @@ gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, ...@@ -112,11 +112,8 @@ gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
} // anonymous namespace } // anonymous namespace
IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) IndexDataManager::IndexDataManager(BufferFactoryD3D *factory)
: mFactory(factory), : mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt()
mRendererClass(rendererClass),
mStreamingBufferShort(),
mStreamingBufferInt()
{ {
} }
...@@ -130,59 +127,6 @@ void IndexDataManager::deinitialize() ...@@ -130,59 +127,6 @@ void IndexDataManager::deinitialize()
mStreamingBufferInt.reset(); mStreamingBufferInt.reset();
} }
// static
bool IndexDataManager::UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
GLenum type,
RendererClass rendererClass)
{
// We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
// indices, since we restrict it via MAX_ELEMENT_INDEX.
return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT &&
rendererClass == RENDERER_D3D11);
}
// static
bool IndexDataManager::IsStreamingIndexData(const gl::Context *context,
GLenum srcType,
RendererClass rendererClass)
{
const auto &glState = context->getGLState();
bool primitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType, rendererClass);
gl::Buffer *glBuffer = glState.getVertexArray()->getElementArrayBuffer().get();
// Case 1: the indices are passed by pointer, which forces the streaming of index data
if (glBuffer == nullptr)
{
return true;
}
BufferD3D *buffer = GetImplAs<BufferD3D>(glBuffer);
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
? GL_UNSIGNED_INT
: GL_UNSIGNED_SHORT;
// Case 2a: the buffer can be used directly
if (buffer->supportsDirectBinding() && dstType == srcType)
{
return false;
}
// Case 2b: use a static translated copy or fall back to streaming
StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
if (staticBuffer == nullptr)
{
return true;
}
if ((staticBuffer->getBufferSize() == 0) || (staticBuffer->getIndexType() != dstType))
{
return true;
}
return false;
}
// This function translates a GL-style indices into DX-style indices, with their description // This function translates a GL-style indices into DX-style indices, with their description
// returned in translated. // returned in translated.
// GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not // GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not
...@@ -193,31 +137,12 @@ bool IndexDataManager::IsStreamingIndexData(const gl::Context *context, ...@@ -193,31 +137,12 @@ bool IndexDataManager::IsStreamingIndexData(const gl::Context *context,
// translated copy of the index buffer. // translated copy of the index buffer.
gl::Error IndexDataManager::prepareIndexData(const gl::Context *context, gl::Error IndexDataManager::prepareIndexData(const gl::Context *context,
GLenum srcType, GLenum srcType,
GLenum dstType,
GLsizei count, GLsizei count,
gl::Buffer *glBuffer, gl::Buffer *glBuffer,
const void *indices, const void *indices,
TranslatedIndexData *translated, TranslatedIndexData *translated)
bool primitiveRestartFixedIndexEnabled)
{ {
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
bool hasPrimitiveRestartIndex =
translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
bool primitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(primitiveRestartFixedIndexEnabled, srcType, mRendererClass) &&
hasPrimitiveRestartIndex;
// We should never have to deal with MAX_UINT indices, since we restrict it via
// MAX_ELEMENT_INDEX.
ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
(hasPrimitiveRestartIndex && translated->indexRange.vertexIndexCount != 0) &&
srcType == GL_UNSIGNED_INT));
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
? GL_UNSIGNED_INT
: GL_UNSIGNED_SHORT;
const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType); const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType);
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
...@@ -229,6 +154,10 @@ gl::Error IndexDataManager::prepareIndexData(const gl::Context *context, ...@@ -229,6 +154,10 @@ gl::Error IndexDataManager::prepareIndexData(const gl::Context *context,
translated->srcIndexData.srcIndexType = srcType; translated->srcIndexData.srcIndexType = srcType;
translated->srcIndexData.srcCount = count; translated->srcIndexData.srcCount = count;
// Context can be nullptr in perf tests.
bool primitiveRestartFixedIndexEnabled =
context ? context->getGLState().isPrimitiveRestartEnabled() : false;
// 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)
{ {
...@@ -349,4 +278,22 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, ...@@ -349,4 +278,22 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
*outBuffer = streamingBuffer.get(); *outBuffer = streamingBuffer.get();
return gl::NoError(); return gl::NoError();
} }
GLenum GetIndexTranslationDestType(GLenum srcType,
const gl::IndexRange &indexRange,
bool usePrimitiveRestartWorkaround)
{
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
if (usePrimitiveRestartWorkaround)
{
if (indexRange.end == gl::GetPrimitiveRestartIndex(srcType))
{
return GL_UNSIGNED_INT;
}
}
return (srcType == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
}
} // namespace rx } // namespace rx
...@@ -65,24 +65,18 @@ struct TranslatedIndexData ...@@ -65,24 +65,18 @@ struct TranslatedIndexData
class IndexDataManager : angle::NonCopyable class IndexDataManager : angle::NonCopyable
{ {
public: public:
explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); explicit IndexDataManager(BufferFactoryD3D *factory);
virtual ~IndexDataManager(); virtual ~IndexDataManager();
void deinitialize(); void deinitialize();
static bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
GLenum type,
RendererClass rendererClass);
static bool IsStreamingIndexData(const gl::Context *context,
GLenum srcType,
RendererClass rendererClass);
gl::Error prepareIndexData(const gl::Context *context, gl::Error prepareIndexData(const gl::Context *context,
GLenum srcType, GLenum srcType,
GLenum dstType,
GLsizei count, GLsizei count,
gl::Buffer *glBuffer, gl::Buffer *glBuffer,
const void *indices, const void *indices,
TranslatedIndexData *translated, TranslatedIndexData *translated);
bool primitiveRestartFixedIndexEnabled);
private: private:
gl::Error streamIndexData(const void *data, gl::Error streamIndexData(const void *data,
...@@ -97,10 +91,14 @@ class IndexDataManager : angle::NonCopyable ...@@ -97,10 +91,14 @@ class IndexDataManager : angle::NonCopyable
using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>; using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>;
BufferFactoryD3D *const mFactory; BufferFactoryD3D *const mFactory;
RendererClass mRendererClass;
std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort; std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort;
std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt; std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt;
}; };
GLenum GetIndexTranslationDestType(GLenum srcType,
const gl::IndexRange &indexRange,
bool usePrimitiveRestartWorkaround);
} // namespace rx } // namespace rx
#endif // LIBANGLE_INDEXDATAMANAGER_H_ #endif // LIBANGLE_INDEXDATAMANAGER_H_
...@@ -1648,8 +1648,7 @@ gl::Error Renderer11::drawElements(const gl::Context *context, ...@@ -1648,8 +1648,7 @@ gl::Error Renderer11::drawElements(const gl::Context *context,
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
if (!DrawCallNeedsTranslation(context, mode) && if (!DrawCallNeedsTranslation(context, mode) &&
!IndexDataManager::UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type, !UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type))
RENDERER_D3D11))
{ {
ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, &indexInfo)); ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, &indexInfo));
...@@ -1805,8 +1804,7 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context, ...@@ -1805,8 +1804,7 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
TranslatedIndexData indexInfo; TranslatedIndexData indexInfo;
if (!DrawCallNeedsTranslation(context, mode) && if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
!IndexDataManager::IsStreamingIndexData(context, type, RENDERER_D3D11))
{ {
ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, &indexInfo)); ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, &indexInfo));
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, 0, 0, 0, &indexInfo)); ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, 0, 0, 0, &indexInfo));
......
...@@ -551,7 +551,7 @@ StateManager11::StateManager11(Renderer11 *renderer) ...@@ -551,7 +551,7 @@ StateManager11::StateManager11(Renderer11 *renderer)
mAppliedIBFormat(DXGI_FORMAT_UNKNOWN), mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
mAppliedIBOffset(0), mAppliedIBOffset(0),
mVertexDataManager(renderer), mVertexDataManager(renderer),
mIndexDataManager(renderer, RENDERER_D3D11), mIndexDataManager(renderer),
mIsMultiviewEnabled(false), mIsMultiviewEnabled(false),
mEmptySerial(mRenderer->generateSerial()), mEmptySerial(mRenderer->generateSerial()),
mIsTransformFeedbackCurrentlyActiveUnpaused(false) mIsTransformFeedbackCurrentlyActiveUnpaused(false)
...@@ -2564,8 +2564,15 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, ...@@ -2564,8 +2564,15 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
gl::VertexArray *vao = glState.getVertexArray(); gl::VertexArray *vao = glState.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, count, elementArrayBuffer, indices,
indexInfo, glState.isPrimitiveRestartEnabled())); bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
GLenum dstType =
GetIndexTranslationDestType(type, indexInfo->indexRange, usePrimitiveRestartWorkaround);
ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, dstType, count, elementArrayBuffer,
indices, indexInfo));
ID3D11Buffer *buffer = nullptr; ID3D11Buffer *buffer = nullptr;
DXGI_FORMAT bufferFormat = DXGI_FORMAT bufferFormat =
......
...@@ -12,15 +12,21 @@ ...@@ -12,15 +12,21 @@
#include <algorithm> #include <algorithm>
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/formatutils.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
#include "libANGLE/State.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" #include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/driver_utils.h" #include "libANGLE/renderer/driver_utils.h"
#include "platform/Platform.h" #include "platform/Platform.h"
#include "platform/WorkaroundsD3D.h" #include "platform/WorkaroundsD3D.h"
...@@ -2315,4 +2321,51 @@ bool UsePresentPathFast(const Renderer11 *renderer, ...@@ -2315,4 +2321,51 @@ bool UsePresentPathFast(const Renderer11 *renderer,
renderer->presentPathFastEnabled()); renderer->presentPathFastEnabled());
} }
bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type)
{
// We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
// indices, since we restrict it via MAX_ELEMENT_INDEX.
return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT);
}
bool IsStreamingIndexData(const gl::Context *context, GLenum srcType)
{
const auto &glState = context->getGLState();
gl::Buffer *glBuffer = glState.getVertexArray()->getElementArrayBuffer().get();
// Case 1: the indices are passed by pointer, which forces the streaming of index data
if (glBuffer == nullptr)
{
return true;
}
bool primitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
BufferD3D *buffer = GetImplAs<BufferD3D>(glBuffer);
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
? GL_UNSIGNED_INT
: GL_UNSIGNED_SHORT;
// Case 2a: the buffer can be used directly
if (buffer->supportsDirectBinding() && dstType == srcType)
{
return false;
}
// Case 2b: use a static translated copy or fall back to streaming
StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
if (staticBuffer == nullptr)
{
return true;
}
if ((staticBuffer->getBufferSize() == 0) || (staticBuffer->getIndexType() != dstType))
{
return true;
}
return false;
}
} // namespace rx } // namespace rx
...@@ -388,6 +388,8 @@ enum class StagingAccess ...@@ -388,6 +388,8 @@ enum class StagingAccess
}; };
bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type);
bool IsStreamingIndexData(const gl::Context *context, GLenum srcType);
// Used for state change notifications between buffers and vertex arrays. // Used for state change notifications between buffers and vertex arrays.
using OnBufferDataDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>; using OnBufferDataDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>;
......
...@@ -380,7 +380,7 @@ egl::Error Renderer9::initializeDevice() ...@@ -380,7 +380,7 @@ egl::Error Renderer9::initializeDevice()
ASSERT(!mVertexDataManager && !mIndexDataManager); ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this); mVertexDataManager = new VertexDataManager(this);
mIndexDataManager = new IndexDataManager(this, getRendererClass()); mIndexDataManager = new IndexDataManager(this);
if (mVertexDataManager->initialize().isError()) if (mVertexDataManager->initialize().isError())
{ {
...@@ -1342,8 +1342,11 @@ gl::Error Renderer9::applyIndexBuffer(const gl::Context *context, ...@@ -1342,8 +1342,11 @@ gl::Error Renderer9::applyIndexBuffer(const gl::Context *context,
{ {
gl::VertexArray *vao = context->getGLState().getVertexArray(); gl::VertexArray *vao = context->getGLState().getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, count, elementArrayBuffer, indices,
indexInfo, false)); GLenum dstType = GetIndexTranslationDestType(type, indexInfo->indexRange, false);
ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer,
indices, indexInfo));
// Directly binding the storage buffer is not supported for d3d9 // Directly binding the storage buffer is not supported for d3d9
ASSERT(indexInfo->storage == nullptr); ASSERT(indexInfo->storage == nullptr);
......
...@@ -155,7 +155,7 @@ class IndexDataManagerPerfTest : public ANGLEPerfTest ...@@ -155,7 +155,7 @@ class IndexDataManagerPerfTest : public ANGLEPerfTest
IndexDataManagerPerfTest::IndexDataManagerPerfTest() IndexDataManagerPerfTest::IndexDataManagerPerfTest()
: ANGLEPerfTest("IndexDataManger", "_run"), : ANGLEPerfTest("IndexDataManger", "_run"),
mIndexDataManager(&mMockBufferFactory, rx::RENDERER_D3D11), mIndexDataManager(&mMockBufferFactory),
mIndexCount(4000), mIndexCount(4000),
mBufferSize(mIndexCount * sizeof(GLushort)), mBufferSize(mIndexCount * sizeof(GLushort)),
mMockBufferFactory(mBufferSize, GL_UNSIGNED_SHORT), mMockBufferFactory(mBufferSize, GL_UNSIGNED_SHORT),
...@@ -176,13 +176,14 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest() ...@@ -176,13 +176,14 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest()
void IndexDataManagerPerfTest::step() void IndexDataManagerPerfTest::step()
{ {
rx::TranslatedIndexData translatedIndexData; rx::TranslatedIndexData translatedIndexData;
gl::IndexRange indexRange;
for (unsigned int iteration = 0; iteration < 100; ++iteration) for (unsigned int iteration = 0; iteration < 100; ++iteration)
{ {
(void)mIndexBuffer.getIndexRange(nullptr, GL_UNSIGNED_SHORT, 0, mIndexCount, false, (void)mIndexBuffer.getIndexRange(nullptr, GL_UNSIGNED_SHORT, 0, mIndexCount, false,
&translatedIndexData.indexRange); &indexRange);
(void)mIndexDataManager.prepareIndexData(nullptr, GL_UNSIGNED_SHORT, mIndexCount, (void)mIndexDataManager.prepareIndexData(nullptr, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
&mIndexBuffer, nullptr, &translatedIndexData, mIndexCount, &mIndexBuffer, nullptr,
false); &translatedIndexData);
} }
} }
......
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