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,
} // anonymous namespace
IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
: mFactory(factory),
mRendererClass(rendererClass),
mStreamingBufferShort(),
mStreamingBufferInt()
IndexDataManager::IndexDataManager(BufferFactoryD3D *factory)
: mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt()
{
}
......@@ -130,59 +127,6 @@ void IndexDataManager::deinitialize()
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
// returned in translated.
// 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,
// translated copy of the index buffer.
gl::Error IndexDataManager::prepareIndexData(const gl::Context *context,
GLenum srcType,
GLenum dstType,
GLsizei count,
gl::Buffer *glBuffer,
const void *indices,
TranslatedIndexData *translated,
bool primitiveRestartFixedIndexEnabled)
TranslatedIndexData *translated)
{
// 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 &dstTypeInfo = gl::GetTypeInfo(dstType);
......@@ -229,6 +154,10 @@ gl::Error IndexDataManager::prepareIndexData(const gl::Context *context,
translated->srcIndexData.srcIndexType = srcType;
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
if (glBuffer == nullptr)
{
......@@ -349,4 +278,22 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
*outBuffer = streamingBuffer.get();
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
......@@ -65,24 +65,18 @@ struct TranslatedIndexData
class IndexDataManager : angle::NonCopyable
{
public:
explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
explicit IndexDataManager(BufferFactoryD3D *factory);
virtual ~IndexDataManager();
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,
GLenum srcType,
GLenum dstType,
GLsizei count,
gl::Buffer *glBuffer,
const void *indices,
TranslatedIndexData *translated,
bool primitiveRestartFixedIndexEnabled);
TranslatedIndexData *translated);
private:
gl::Error streamIndexData(const void *data,
......@@ -97,10 +91,14 @@ class IndexDataManager : angle::NonCopyable
using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>;
BufferFactoryD3D *const mFactory;
RendererClass mRendererClass;
std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort;
std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt;
};
GLenum GetIndexTranslationDestType(GLenum srcType,
const gl::IndexRange &indexRange,
bool usePrimitiveRestartWorkaround);
} // namespace rx
#endif // LIBANGLE_INDEXDATAMANAGER_H_
......@@ -1648,8 +1648,7 @@ gl::Error Renderer11::drawElements(const gl::Context *context,
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
if (!DrawCallNeedsTranslation(context, mode) &&
!IndexDataManager::UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type,
RENDERER_D3D11))
!UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type))
{
ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, &indexInfo));
......@@ -1805,8 +1804,7 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
TranslatedIndexData indexInfo;
if (!DrawCallNeedsTranslation(context, mode) &&
!IndexDataManager::IsStreamingIndexData(context, type, RENDERER_D3D11))
if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
{
ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, &indexInfo));
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, 0, 0, 0, &indexInfo));
......
......@@ -551,7 +551,7 @@ StateManager11::StateManager11(Renderer11 *renderer)
mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
mAppliedIBOffset(0),
mVertexDataManager(renderer),
mIndexDataManager(renderer, RENDERER_D3D11),
mIndexDataManager(renderer),
mIsMultiviewEnabled(false),
mEmptySerial(mRenderer->generateSerial()),
mIsTransformFeedbackCurrentlyActiveUnpaused(false)
......@@ -2564,8 +2564,15 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
const auto &glState = context->getGLState();
gl::VertexArray *vao = glState.getVertexArray();
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;
DXGI_FORMAT bufferFormat =
......
......@@ -12,15 +12,21 @@
#include <algorithm>
#include "common/debug.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.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/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/FramebufferD3D.h"
#include "libANGLE/renderer/driver_utils.h"
#include "platform/Platform.h"
#include "platform/WorkaroundsD3D.h"
......@@ -2315,4 +2321,51 @@ bool UsePresentPathFast(const Renderer11 *renderer,
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
......@@ -388,6 +388,8 @@ enum class StagingAccess
};
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.
using OnBufferDataDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>;
......
......@@ -380,7 +380,7 @@ egl::Error Renderer9::initializeDevice()
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
mIndexDataManager = new IndexDataManager(this, getRendererClass());
mIndexDataManager = new IndexDataManager(this);
if (mVertexDataManager->initialize().isError())
{
......@@ -1342,8 +1342,11 @@ gl::Error Renderer9::applyIndexBuffer(const gl::Context *context,
{
gl::VertexArray *vao = context->getGLState().getVertexArray();
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
ASSERT(indexInfo->storage == nullptr);
......
......@@ -155,7 +155,7 @@ class IndexDataManagerPerfTest : public ANGLEPerfTest
IndexDataManagerPerfTest::IndexDataManagerPerfTest()
: ANGLEPerfTest("IndexDataManger", "_run"),
mIndexDataManager(&mMockBufferFactory, rx::RENDERER_D3D11),
mIndexDataManager(&mMockBufferFactory),
mIndexCount(4000),
mBufferSize(mIndexCount * sizeof(GLushort)),
mMockBufferFactory(mBufferSize, GL_UNSIGNED_SHORT),
......@@ -176,13 +176,14 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest()
void IndexDataManagerPerfTest::step()
{
rx::TranslatedIndexData translatedIndexData;
gl::IndexRange indexRange;
for (unsigned int iteration = 0; iteration < 100; ++iteration)
{
(void)mIndexBuffer.getIndexRange(nullptr, GL_UNSIGNED_SHORT, 0, mIndexCount, false,
&translatedIndexData.indexRange);
(void)mIndexDataManager.prepareIndexData(nullptr, GL_UNSIGNED_SHORT, mIndexCount,
&mIndexBuffer, nullptr, &translatedIndexData,
false);
&indexRange);
(void)mIndexDataManager.prepareIndexData(nullptr, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
mIndexCount, &mIndexBuffer, nullptr,
&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