Move the vertex data manager and vertex declaration cache from Context to Renderer9.

TRAC #22016 Signed-off-by: Daniel Koch Signed-off-by: Shannon Woods Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1474 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 92025f56
...@@ -153,7 +153,6 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n ...@@ -153,7 +153,6 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
mState.unpackAlignment = 4; mState.unpackAlignment = 4;
mState.packReverseRowOrder = false; mState.packReverseRowOrder = false;
mVertexDataManager = NULL;
mIndexDataManager = NULL; mIndexDataManager = NULL;
mLineLoopIB = NULL; mLineLoopIB = NULL;
...@@ -237,7 +236,6 @@ Context::~Context() ...@@ -237,7 +236,6 @@ Context::~Context()
mTexture2DZero.set(NULL); mTexture2DZero.set(NULL);
mTextureCubeMapZero.set(NULL); mTextureCubeMapZero.set(NULL);
delete mVertexDataManager;
delete mIndexDataManager; delete mIndexDataManager;
delete mLineLoopIB; delete mLineLoopIB;
...@@ -255,7 +253,6 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -255,7 +253,6 @@ void Context::makeCurrent(egl::Surface *surface)
if (!mHasBeenCurrent) if (!mHasBeenCurrent)
{ {
mVertexDataManager = new VertexDataManager(mRenderer);
mIndexDataManager = new IndexDataManager(mRenderer); mIndexDataManager = new IndexDataManager(mRenderer);
mSupportsShaderModel3 = mRenderer->getShaderModel3Support(); mSupportsShaderModel3 = mRenderer->getShaderModel3Support();
...@@ -349,8 +346,6 @@ void Context::markAllStateDirty() ...@@ -349,8 +346,6 @@ void Context::markAllStateDirty()
mAppliedProgramBinarySerial = 0; mAppliedProgramBinarySerial = 0;
mAppliedIBSerial = 0; mAppliedIBSerial = 0;
mVertexDeclarationCache.markStateDirty();
mDxUniformsDirty = true; mDxUniformsDirty = true;
} }
...@@ -1854,18 +1849,6 @@ void Context::applyState(GLenum drawMode) ...@@ -1854,18 +1849,6 @@ void Context::applyState(GLenum drawMode)
mState.rasterizer.frontFace == GL_CCW, stencilSize); mState.rasterizer.frontFace == GL_CCW, stencilSize);
} }
GLenum Context::applyVertexBuffer(ProgramBinary *programBinary, VertexAttributeArray &vertexAttributes, GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
{
TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
if (err != GL_NO_ERROR)
{
return err;
}
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw);
}
// Applies the indices and element array bindings to the Direct3D 9 device // Applies the indices and element array bindings to the Direct3D 9 device
GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
{ {
...@@ -2267,7 +2250,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -2267,7 +2250,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
ProgramBinary *programBinary = getCurrentProgramBinary(); ProgramBinary *programBinary = getCurrentProgramBinary();
GLsizei repeatDraw = 1; GLsizei repeatDraw = 1;
GLenum err = applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances, &repeatDraw); GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances, &repeatDraw);
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
return error(err); return error(err);
...@@ -2359,7 +2342,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -2359,7 +2342,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
GLsizei repeatDraw = 1; GLsizei repeatDraw = 1;
err = applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances, &repeatDraw); err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances, &repeatDraw);
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
return error(err); return error(err);
...@@ -3012,8 +2995,6 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values) ...@@ -3012,8 +2995,6 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values)
mState.vertexAttribute[index].mCurrentValue[1] = values[1]; mState.vertexAttribute[index].mCurrentValue[1] = values[1];
mState.vertexAttribute[index].mCurrentValue[2] = values[2]; mState.vertexAttribute[index].mCurrentValue[2] = values[2];
mState.vertexAttribute[index].mCurrentValue[3] = values[3]; mState.vertexAttribute[index].mCurrentValue[3] = values[3];
mVertexDataManager->dirtyCurrentValue(index);
} }
void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
...@@ -3406,197 +3387,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 ...@@ -3406,197 +3387,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
} }
} }
VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
mVertexDeclCache[i].vertexDeclaration = NULL;
mVertexDeclCache[i].lruCount = 0;
}
}
VertexDeclarationCache::~VertexDeclarationCache()
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].vertexDeclaration)
{
mVertexDeclCache[i].vertexDeclaration->Release();
}
}
}
GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
{
*repeatDraw = 1;
int indexedAttribute = MAX_VERTEX_ATTRIBS;
int instancedAttribute = MAX_VERTEX_ATTRIBS;
if (instances > 0)
{
// Find an indexed attribute to be mapped to D3D stream 0
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
if (indexedAttribute == MAX_VERTEX_ATTRIBS)
{
if (attributes[i].divisor == 0)
{
indexedAttribute = i;
}
}
else if (instancedAttribute == MAX_VERTEX_ATTRIBS)
{
if (attributes[i].divisor != 0)
{
instancedAttribute = i;
}
}
else break; // Found both an indexed and instanced attribute
}
}
if (indexedAttribute == MAX_VERTEX_ATTRIBS)
{
return GL_INVALID_OPERATION;
}
}
D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0];
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
int stream = i;
if (instances > 0)
{
// Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
if (instancedAttribute == MAX_VERTEX_ATTRIBS)
{
*repeatDraw = instances;
}
else
{
if (i == indexedAttribute)
{
stream = 0;
}
else if (i == 0)
{
stream = indexedAttribute;
}
UINT frequency = 1;
if (attributes[i].divisor == 0)
{
frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
}
else
{
frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
}
device->SetStreamSourceFreq(stream, frequency);
mInstancingEnabled = true;
}
}
if (mAppliedVBs[stream].serial != attributes[i].serial ||
mAppliedVBs[stream].stride != attributes[i].stride ||
mAppliedVBs[stream].offset != attributes[i].offset)
{
device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
mAppliedVBs[stream].serial = attributes[i].serial;
mAppliedVBs[stream].stride = attributes[i].stride;
mAppliedVBs[stream].offset = attributes[i].offset;
}
element->Stream = stream;
element->Offset = 0;
element->Type = attributes[i].type;
element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD;
element->UsageIndex = programBinary->getSemanticIndex(i);
element++;
}
}
if (instances == 0 || instancedAttribute == MAX_VERTEX_ATTRIBS)
{
if (mInstancingEnabled)
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
device->SetStreamSourceFreq(i, 1);
}
mInstancingEnabled = false;
}
}
static const D3DVERTEXELEMENT9 end = D3DDECL_END();
*(element++) = end;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
{
entry->lruCount = ++mMaxLru;
if(entry->vertexDeclaration != mLastSetVDecl)
{
device->SetVertexDeclaration(entry->vertexDeclaration);
mLastSetVDecl = entry->vertexDeclaration;
}
return GL_NO_ERROR;
}
}
VertexDeclCacheEntry *lastCache = mVertexDeclCache;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
{
lastCache = &mVertexDeclCache[i];
}
}
if (lastCache->vertexDeclaration != NULL)
{
lastCache->vertexDeclaration->Release();
lastCache->vertexDeclaration = NULL;
// mLastSetVDecl is set to the replacement, so we don't have to worry
// about it.
}
memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
device->SetVertexDeclaration(lastCache->vertexDeclaration);
mLastSetVDecl = lastCache->vertexDeclaration;
lastCache->lruCount = ++mMaxLru;
return GL_NO_ERROR;
}
void VertexDeclarationCache::markStateDirty()
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mAppliedVBs[i].serial = 0;
}
mLastSetVDecl = NULL;
mInstancingEnabled = true; // Forces it to be disabled when not used
}
} }
extern "C" extern "C"
......
...@@ -59,7 +59,6 @@ class Depthbuffer; ...@@ -59,7 +59,6 @@ class Depthbuffer;
class StreamingIndexBuffer; class StreamingIndexBuffer;
class Stencilbuffer; class Stencilbuffer;
class DepthStencilbuffer; class DepthStencilbuffer;
class VertexDataManager;
class IndexDataManager; class IndexDataManager;
class Fence; class Fence;
class Query; class Query;
...@@ -145,8 +144,6 @@ class VertexAttribute ...@@ -145,8 +144,6 @@ class VertexAttribute
unsigned int mDivisor; unsigned int mDivisor;
}; };
typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];
// Helper structure to store all raw state // Helper structure to store all raw state
struct State struct State
{ {
...@@ -193,41 +190,6 @@ struct State ...@@ -193,41 +190,6 @@ struct State
bool packReverseRowOrder; bool packReverseRowOrder;
}; };
// Helper class to construct and cache vertex declarations
class VertexDeclarationCache
{
public:
VertexDeclarationCache();
~VertexDeclarationCache();
GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
void markStateDirty();
private:
UINT mMaxLru;
enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
struct VBData
{
unsigned int serial;
unsigned int stride;
unsigned int offset;
};
VBData mAppliedVBs[MAX_VERTEX_ATTRIBS];
IDirect3DVertexDeclaration9 *mLastSetVDecl;
bool mInstancingEnabled;
struct VertexDeclCacheEntry
{
D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1];
UINT lruCount;
IDirect3DVertexDeclaration9 *vertexDeclaration;
} mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
};
class Context class Context
{ {
public: public:
...@@ -471,7 +433,6 @@ class Context ...@@ -471,7 +433,6 @@ class Context
bool applyRenderTarget(bool ignoreViewport); bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode); void applyState(GLenum drawMode);
GLenum applyVertexBuffer(ProgramBinary *programBinary, VertexAttributeArray &vertexAttributes, GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders(); void applyShaders();
void applyTextures(); void applyTextures();
...@@ -521,7 +482,6 @@ class Context ...@@ -521,7 +482,6 @@ class Context
std::string mExtensionString; std::string mExtensionString;
std::string mRendererString; std::string mRendererString;
VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager; IndexDataManager *mIndexDataManager;
StreamingIndexBuffer *mLineLoopIB; StreamingIndexBuffer *mLineLoopIB;
...@@ -582,8 +542,6 @@ class Context ...@@ -582,8 +542,6 @@ class Context
IDirect3DStateBlock9 *mMaskedClearSavedState; IDirect3DStateBlock9 *mMaskedClearSavedState;
ResourceManager *mResourceManager; ResourceManager *mResourceManager;
VertexDeclarationCache mVertexDeclarationCache;
}; };
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "libGLESv2/vertexconversion.h" #include "libGLESv2/vertexconversion.h"
#include "libGLESv2/IndexDataManager.h" #include "libGLESv2/IndexDataManager.h"
#include <limits>
namespace namespace
{ {
enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
...@@ -41,7 +43,10 @@ VertexDataManager::VertexDataManager(rx::Renderer9 *renderer) : mRenderer(render ...@@ -41,7 +43,10 @@ VertexDataManager::VertexDataManager(rx::Renderer9 *renderer) : mRenderer(render
{ {
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{ {
mDirtyCurrentValue[i] = true; mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN();
mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN();
mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN();
mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN();
mCurrentValueBuffer[i] = NULL; mCurrentValueBuffer[i] = NULL;
mCurrentValueOffsets[i] = 0; mCurrentValueOffsets[i] = 0;
} }
...@@ -121,7 +126,7 @@ std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffe ...@@ -121,7 +126,7 @@ std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffe
return streamOffset; return streamOffset;
} }
GLenum VertexDataManager::prepareVertexData(const VertexAttributeArray &attribs, ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) GLenum VertexDataManager::prepareVertexData(const VertexAttribute attribs[], ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
{ {
if (!mStreamingBuffer) if (!mStreamingBuffer)
{ {
...@@ -267,7 +272,10 @@ GLenum VertexDataManager::prepareVertexData(const VertexAttributeArray &attribs, ...@@ -267,7 +272,10 @@ GLenum VertexDataManager::prepareVertexData(const VertexAttributeArray &attribs,
StreamingVertexBuffer *buffer = mCurrentValueBuffer[i]; StreamingVertexBuffer *buffer = mCurrentValueBuffer[i];
if (mDirtyCurrentValue[i]) if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] ||
mCurrentValue[i][1] != attribs[i].mCurrentValue[1] ||
mCurrentValue[i][2] != attribs[i].mCurrentValue[2] ||
mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
{ {
const int requiredSpace = 4 * sizeof(float); const int requiredSpace = 4 * sizeof(float);
buffer->addRequiredSpace(requiredSpace); buffer->addRequiredSpace(requiredSpace);
...@@ -280,7 +288,11 @@ GLenum VertexDataManager::prepareVertexData(const VertexAttributeArray &attribs, ...@@ -280,7 +288,11 @@ GLenum VertexDataManager::prepareVertexData(const VertexAttributeArray &attribs,
data[2] = attribs[i].mCurrentValue[2]; data[2] = attribs[i].mCurrentValue[2];
data[3] = attribs[i].mCurrentValue[3]; data[3] = attribs[i].mCurrentValue[3];
buffer->unmap(); buffer->unmap();
mDirtyCurrentValue[i] = false;
mCurrentValue[i][0] = attribs[i].mCurrentValue[0];
mCurrentValue[i][1] = attribs[i].mCurrentValue[1];
mCurrentValue[i][2] = attribs[i].mCurrentValue[2];
mCurrentValue[i][3] = attribs[i].mCurrentValue[3];
} }
} }
......
...@@ -116,9 +116,7 @@ class VertexDataManager ...@@ -116,9 +116,7 @@ class VertexDataManager
VertexDataManager(rx::Renderer9 *renderer); VertexDataManager(rx::Renderer9 *renderer);
virtual ~VertexDataManager(); virtual ~VertexDataManager();
void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } GLenum prepareVertexData(const VertexAttribute attribs[], ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
GLenum prepareVertexData(const VertexAttributeArray &attribs, ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
private: private:
DISALLOW_COPY_AND_ASSIGN(VertexDataManager); DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
...@@ -130,7 +128,7 @@ class VertexDataManager ...@@ -130,7 +128,7 @@ class VertexDataManager
StreamingVertexBuffer *mStreamingBuffer; StreamingVertexBuffer *mStreamingBuffer;
bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; float mCurrentValue[MAX_VERTEX_ATTRIBS][4];
StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];
std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS]; std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS];
......
...@@ -40,6 +40,7 @@ class Display; ...@@ -40,6 +40,7 @@ class Display;
namespace gl namespace gl
{ {
class ProgramBinary; class ProgramBinary;
class VertexAttribute;
} }
namespace rx namespace rx
...@@ -92,6 +93,8 @@ class Renderer ...@@ -92,6 +93,8 @@ class Renderer
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw) = 0;
virtual void clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear, virtual void clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear,
gl::Framebuffer *frameBuffer) = 0; gl::Framebuffer *frameBuffer) = 0;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "libGLESv2/Framebuffer.h" #include "libGLESv2/Framebuffer.h"
#include "libGLESv2/Program.h" #include "libGLESv2/Program.h"
#include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/VertexDataManager.h"
#include "libGLESv2/renderer/Renderer9.h" #include "libGLESv2/renderer/Renderer9.h"
#include "libGLESv2/renderer/renderer9_utils.h" #include "libGLESv2/renderer/renderer9_utils.h"
#include "libGLESv2/renderer/SwapChain9.h" #include "libGLESv2/renderer/SwapChain9.h"
...@@ -85,6 +86,8 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend ...@@ -85,6 +86,8 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend
mDeviceLost = false; mDeviceLost = false;
mMaxSupportedSamples = 0; mMaxSupportedSamples = 0;
mVertexDataManager = NULL;
} }
Renderer9::~Renderer9() Renderer9::~Renderer9()
...@@ -390,6 +393,11 @@ void Renderer9::initializeDevice() ...@@ -390,6 +393,11 @@ void Renderer9::initializeDevice()
markAllStateDirty(); markAllStateDirty();
mSceneStarted = false; mSceneStarted = false;
if (!mVertexDataManager)
{
mVertexDataManager = new gl::VertexDataManager(this);
}
} }
D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
...@@ -1083,6 +1091,18 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) ...@@ -1083,6 +1091,18 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
return true; return true;
} }
GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
{
gl::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
if (err != GL_NO_ERROR)
{
return err;
}
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw);
}
void Renderer9::clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear, void Renderer9::clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear,
gl::Framebuffer *frameBuffer) gl::Framebuffer *frameBuffer)
{ {
...@@ -1104,6 +1124,8 @@ void Renderer9::markAllStateDirty() ...@@ -1104,6 +1124,8 @@ void Renderer9::markAllStateDirty()
mForceSetBlendState = true; mForceSetBlendState = true;
mForceSetScissor = true; mForceSetScissor = true;
mForceSetViewport = true; mForceSetViewport = true;
mVertexDeclarationCache.markStateDirty();
} }
void Renderer9::releaseDeviceResources() void Renderer9::releaseDeviceResources()
...@@ -1116,6 +1138,9 @@ void Renderer9::releaseDeviceResources() ...@@ -1116,6 +1138,9 @@ void Renderer9::releaseDeviceResources()
mVertexShaderCache.clear(); mVertexShaderCache.clear();
mPixelShaderCache.clear(); mPixelShaderCache.clear();
delete mVertexDataManager;
mVertexDataManager = NULL;
} }
...@@ -2170,4 +2195,203 @@ bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *s ...@@ -2170,4 +2195,203 @@ bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *s
return true; return true;
} }
VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
mVertexDeclCache[i].vertexDeclaration = NULL;
mVertexDeclCache[i].lruCount = 0;
}
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mAppliedVBs[i].serial = 0;
}
mLastSetVDecl = NULL;
mInstancingEnabled = true;
}
VertexDeclarationCache::~VertexDeclarationCache()
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].vertexDeclaration)
{
mVertexDeclCache[i].vertexDeclaration->Release();
}
}
}
GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, gl::TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
{
*repeatDraw = 1;
int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;
if (instances > 0)
{
// Find an indexed attribute to be mapped to D3D stream 0
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
{
if (attributes[i].divisor == 0)
{
indexedAttribute = i;
}
}
else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
{
if (attributes[i].divisor != 0)
{
instancedAttribute = i;
}
}
else break; // Found both an indexed and instanced attribute
}
}
if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
{
return GL_INVALID_OPERATION;
}
}
D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0];
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
int stream = i;
if (instances > 0)
{
// Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
{
*repeatDraw = instances;
}
else
{
if (i == indexedAttribute)
{
stream = 0;
}
else if (i == 0)
{
stream = indexedAttribute;
}
UINT frequency = 1;
if (attributes[i].divisor == 0)
{
frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
}
else
{
frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
}
device->SetStreamSourceFreq(stream, frequency);
mInstancingEnabled = true;
}
}
if (mAppliedVBs[stream].serial != attributes[i].serial ||
mAppliedVBs[stream].stride != attributes[i].stride ||
mAppliedVBs[stream].offset != attributes[i].offset)
{
device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
mAppliedVBs[stream].serial = attributes[i].serial;
mAppliedVBs[stream].stride = attributes[i].stride;
mAppliedVBs[stream].offset = attributes[i].offset;
}
element->Stream = stream;
element->Offset = 0;
element->Type = attributes[i].type;
element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD;
element->UsageIndex = programBinary->getSemanticIndex(i);
element++;
}
}
if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
{
if (mInstancingEnabled)
{
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
device->SetStreamSourceFreq(i, 1);
}
mInstancingEnabled = false;
}
}
static const D3DVERTEXELEMENT9 end = D3DDECL_END();
*(element++) = end;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
{
entry->lruCount = ++mMaxLru;
if(entry->vertexDeclaration != mLastSetVDecl)
{
device->SetVertexDeclaration(entry->vertexDeclaration);
mLastSetVDecl = entry->vertexDeclaration;
}
return GL_NO_ERROR;
}
}
VertexDeclCacheEntry *lastCache = mVertexDeclCache;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
{
lastCache = &mVertexDeclCache[i];
}
}
if (lastCache->vertexDeclaration != NULL)
{
lastCache->vertexDeclaration->Release();
lastCache->vertexDeclaration = NULL;
// mLastSetVDecl is set to the replacement, so we don't have to worry
// about it.
}
memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
device->SetVertexDeclaration(lastCache->vertexDeclaration);
mLastSetVDecl = lastCache->vertexDeclaration;
lastCache->lruCount = ++mMaxLru;
return GL_NO_ERROR;
}
void VertexDeclarationCache::markStateDirty()
{
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mAppliedVBs[i].serial = 0;
}
mLastSetVDecl = NULL;
mInstancingEnabled = true; // Forces it to be disabled when not used
}
} }
\ No newline at end of file
...@@ -25,10 +25,51 @@ ...@@ -25,10 +25,51 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libGLESv2/renderer/ShaderCache.h" #include "libGLESv2/renderer/ShaderCache.h"
#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/Context.h"
namespace gl
{
class VertexDataManager;
}
namespace rx namespace rx
{ {
// Helper class to construct and cache vertex declarations
class VertexDeclarationCache
{
public:
VertexDeclarationCache();
~VertexDeclarationCache();
GLenum applyDeclaration(IDirect3DDevice9 *device, gl::TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
void markStateDirty();
private:
UINT mMaxLru;
enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
struct VBData
{
unsigned int serial;
unsigned int stride;
unsigned int offset;
};
VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS];
IDirect3DVertexDeclaration9 *mLastSetVDecl;
bool mInstancingEnabled;
struct VertexDeclCacheEntry
{
D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1];
UINT lruCount;
IDirect3DVertexDeclaration9 *vertexDeclaration;
} mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
};
class Renderer9 : public Renderer class Renderer9 : public Renderer
{ {
public: public:
...@@ -85,6 +126,8 @@ class Renderer9 : public Renderer ...@@ -85,6 +126,8 @@ class Renderer9 : public Renderer
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
virtual void clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear, virtual void clear(GLbitfield mask, const gl::Color &colorClear, float depthClear, int stencilClear,
gl::Framebuffer *frameBuffer); gl::Framebuffer *frameBuffer);
...@@ -244,6 +287,9 @@ class Renderer9 : public Renderer ...@@ -244,6 +287,9 @@ class Renderer9 : public Renderer
std::vector<IDirect3DQuery9*> mEventQueryPool; std::vector<IDirect3DQuery9*> mEventQueryPool;
VertexShaderCache mVertexShaderCache; VertexShaderCache mVertexShaderCache;
PixelShaderCache mPixelShaderCache; PixelShaderCache mPixelShaderCache;
gl::VertexDataManager *mVertexDataManager;
VertexDeclarationCache mVertexDeclarationCache;
}; };
} }
......
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