Set the stream source frequencies for instanced draw calls. Searches for an…

Set the stream source frequencies for instanced draw calls. Searches for an indexed (non-instanced) attribute to ensure it gets mapped to stream 0. TRAC #19489 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@969 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent d2820bfb
......@@ -504,6 +504,11 @@ void Blit::setCommonBlitState()
RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
device->SetScissorRect(&scissorRect);
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
device->SetStreamSourceFreq(i, 1);
}
}
void Blit::render()
......
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
......@@ -2250,7 +2250,7 @@ void Context::applyState(GLenum drawMode)
}
}
GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
GLenum Context::applyVertexBuffer(GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
......@@ -2260,7 +2260,7 @@ GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
return err;
}
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, getCurrentProgram());
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, getCurrentProgram(), instances);
}
// Applies the indices and element array bindings to the Direct3D 9 device
......@@ -2810,6 +2810,11 @@ void Context::clear(GLbitfield mask)
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mDevice->SetStreamSourceFreq(i, 1);
}
hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
......@@ -2869,6 +2874,11 @@ void Context::clear(GLbitfield mask)
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mDevice->SetStreamSourceFreq(i, 1);
}
float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
quad[0][0] = -0.5f;
quad[0][1] = mRenderTargetDesc.Height - 0.5f;
......@@ -2911,7 +2921,7 @@ void Context::clear(GLbitfield mask)
}
}
void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
if (!mState.currentProgram)
{
......@@ -2936,7 +2946,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
applyState(mode);
GLenum err = applyVertexBuffer(first, count);
GLenum err = applyVertexBuffer(first, count, instances);
if (err != GL_NO_ERROR)
{
return error(err);
......@@ -2963,7 +2973,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
}
}
void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
{
if (!mState.currentProgram)
{
......@@ -3001,7 +3011,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
}
GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
err = applyVertexBuffer(indexInfo.minIndex, vertexCount);
err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances);
if (err != GL_NO_ERROR)
{
return error(err);
......@@ -3028,20 +3038,6 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
}
}
void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
UNIMPLEMENTED(); // TODO
drawArrays(mode, first, count);
}
void Context::drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
{
UNIMPLEMENTED(); // TODO
drawElements(mode, count, type, indices);
}
// Implements glFlush when block is false, glFinish when block is true
void Context::sync(bool block)
{
......@@ -3990,8 +3986,28 @@ VertexDeclarationCache::~VertexDeclarationCache()
}
}
GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program)
GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program, GLsizei instances)
{
int indexedAttribute = 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 && attributes[i].divisor == 0)
{
indexedAttribute = i;
break;
}
}
if (indexedAttribute == MAX_VERTEX_ATTRIBS)
{
return GL_INVALID_OPERATION;
}
}
D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0];
......@@ -3999,17 +4015,45 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
{
if (attributes[i].active)
{
if (mAppliedVBs[i].serial != attributes[i].serial ||
mAppliedVBs[i].stride != attributes[i].stride ||
mAppliedVBs[i].offset != attributes[i].offset)
int stream = i;
if (instances > 0)
{
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(i, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
mAppliedVBs[i].serial = attributes[i].serial;
mAppliedVBs[i].stride = attributes[i].stride;
mAppliedVBs[i].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 = i;
element->Stream = stream;
element->Offset = 0;
element->Type = attributes[i].type;
element->Method = D3DDECLMETHOD_DEFAULT;
......@@ -4019,6 +4063,19 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
}
}
if (instances == 0)
{
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;
......@@ -4073,6 +4130,7 @@ void VertexDeclarationCache::markStateDirty()
}
mLastSetVDecl = NULL;
mInstancingEnabled = true; // Forces it to be disabled when not used
}
}
......
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
......@@ -244,7 +244,7 @@ class VertexDeclarationCache
VertexDeclarationCache();
~VertexDeclarationCache();
GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program);
GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program, GLsizei instances);
void markStateDirty();
......@@ -262,6 +262,7 @@ class VertexDeclarationCache
VBData mAppliedVBs[MAX_VERTEX_ATTRIBS];
IDirect3DVertexDeclaration9 *mLastSetVDecl;
bool mInstancingEnabled;
struct VertexDeclCacheEntry
{
......@@ -452,10 +453,8 @@ class Context
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask);
void drawArrays(GLenum mode, GLint first, GLsizei count);
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
void sync(bool block); // flush/finish
// Draw the last segment of a line loop
......@@ -514,7 +513,7 @@ class Context
bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint first, GLsizei count);
GLenum applyVertexBuffer(GLint first, GLsizei count, GLsizei instances);
GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders();
void applyTextures();
......
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
......@@ -245,6 +245,8 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
translated[i].vertexBuffer = vertexBuffer->getBuffer();
translated[i].serial = vertexBuffer->getSerial();
translated[i].divisor = attribs[i].mDivisor;
translated[i].type = converter.d3dDeclType;
translated[i].stride = converter.outputElementSize;
translated[i].offset = streamOffset;
......@@ -277,6 +279,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
translated[i].serial = mCurrentValueBuffer[i]->getSerial();
translated[i].divisor = 0;
translated[i].type = D3DDECLTYPE_FLOAT4;
translated[i].stride = 0;
......
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
......@@ -31,6 +31,7 @@ struct TranslatedAttribute
IDirect3DVertexBuffer9 *vertexBuffer;
unsigned int serial;
unsigned int divisor;
};
class VertexBuffer
......
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
......@@ -1943,7 +1943,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
if (context)
{
context->drawArrays(mode, first, count);
context->drawArrays(mode, first, count, 0);
}
}
catch(std::bad_alloc&)
......@@ -1963,11 +1963,14 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun
return error(GL_INVALID_VALUE);
}
gl::Context *context = gl::getNonLostContext();
if (context)
if (primcount > 0)
{
context->drawArraysInstanced(mode, first, count, primcount);
gl::Context *context = gl::getNonLostContext();
if (context)
{
context->drawArrays(mode, first, count, primcount);
}
}
}
catch(std::bad_alloc&)
......@@ -2007,7 +2010,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
return error(GL_INVALID_ENUM);
}
context->drawElements(mode, count, type, indices);
context->drawElements(mode, count, type, indices, 0);
}
}
catch(std::bad_alloc&)
......@@ -2028,26 +2031,29 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
return error(GL_INVALID_VALUE);
}
gl::Context *context = gl::getNonLostContext();
if (context)
if (primcount > 0)
{
switch (type)
gl::Context *context = gl::getNonLostContext();
if (context)
{
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT:
break;
case GL_UNSIGNED_INT:
if (!context->supports32bitIndices())
switch (type)
{
return error(GL_INVALID_ENUM);
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT:
break;
case GL_UNSIGNED_INT:
if (!context->supports32bitIndices())
{
return error(GL_INVALID_ENUM);
}
break;
default:
return error(GL_INVALID_ENUM);
}
break;
default:
return error(GL_INVALID_ENUM);
context->drawElements(mode, count, type, indices, primcount);
}
context->drawElementsInstanced(mode, count, type, indices, primcount);
}
}
catch(std::bad_alloc&)
......
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