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() ...@@ -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 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
device->SetScissorRect(&scissorRect); device->SetScissorRect(&scissorRect);
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
device->SetStreamSourceFreq(i, 1);
}
} }
void Blit::render() 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 // 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.
// //
...@@ -2250,7 +2250,7 @@ void Context::applyState(GLenum drawMode) ...@@ -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]; TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
...@@ -2260,7 +2260,7 @@ GLenum Context::applyVertexBuffer(GLint first, GLsizei count) ...@@ -2260,7 +2260,7 @@ GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
return err; 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 // Applies the indices and element array bindings to the Direct3D 9 device
...@@ -2810,6 +2810,11 @@ void Context::clear(GLbitfield mask) ...@@ -2810,6 +2810,11 @@ void Context::clear(GLbitfield mask)
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mDevice->SetStreamSourceFreq(i, 1);
}
hr = mDevice->EndStateBlock(&mMaskedClearSavedState); hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
...@@ -2869,6 +2874,11 @@ void Context::clear(GLbitfield mask) ...@@ -2869,6 +2874,11 @@ void Context::clear(GLbitfield mask)
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 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 float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
quad[0][0] = -0.5f; quad[0][0] = -0.5f;
quad[0][1] = mRenderTargetDesc.Height - 0.5f; quad[0][1] = mRenderTargetDesc.Height - 0.5f;
...@@ -2911,7 +2921,7 @@ void Context::clear(GLbitfield mask) ...@@ -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) if (!mState.currentProgram)
{ {
...@@ -2936,7 +2946,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -2936,7 +2946,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
applyState(mode); applyState(mode);
GLenum err = applyVertexBuffer(first, count); GLenum err = applyVertexBuffer(first, count, instances);
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
return error(err); return error(err);
...@@ -2963,7 +2973,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -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) if (!mState.currentProgram)
{ {
...@@ -3001,7 +3011,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -3001,7 +3011,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;
err = applyVertexBuffer(indexInfo.minIndex, vertexCount); err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances);
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
return error(err); return error(err);
...@@ -3028,20 +3038,6 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -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 // Implements glFlush when block is false, glFinish when block is true
void Context::sync(bool block) void Context::sync(bool block)
{ {
...@@ -3990,8 +3986,28 @@ VertexDeclarationCache::~VertexDeclarationCache() ...@@ -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 elements[MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0]; D3DVERTEXELEMENT9 *element = &elements[0];
...@@ -3999,17 +4015,45 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl ...@@ -3999,17 +4015,45 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
{ {
if (attributes[i].active) if (attributes[i].active)
{ {
if (mAppliedVBs[i].serial != attributes[i].serial || int stream = i;
mAppliedVBs[i].stride != attributes[i].stride ||
mAppliedVBs[i].offset != attributes[i].offset) 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); device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
mAppliedVBs[i].serial = attributes[i].serial; mAppliedVBs[stream].serial = attributes[i].serial;
mAppliedVBs[i].stride = attributes[i].stride; mAppliedVBs[stream].stride = attributes[i].stride;
mAppliedVBs[i].offset = attributes[i].offset; mAppliedVBs[stream].offset = attributes[i].offset;
} }
element->Stream = i; element->Stream = stream;
element->Offset = 0; element->Offset = 0;
element->Type = attributes[i].type; element->Type = attributes[i].type;
element->Method = D3DDECLMETHOD_DEFAULT; element->Method = D3DDECLMETHOD_DEFAULT;
...@@ -4019,6 +4063,19 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl ...@@ -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(); static const D3DVERTEXELEMENT9 end = D3DDECL_END();
*(element++) = end; *(element++) = end;
...@@ -4073,6 +4130,7 @@ void VertexDeclarationCache::markStateDirty() ...@@ -4073,6 +4130,7 @@ void VertexDeclarationCache::markStateDirty()
} }
mLastSetVDecl = NULL; 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 // 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.
// //
...@@ -244,7 +244,7 @@ class VertexDeclarationCache ...@@ -244,7 +244,7 @@ class VertexDeclarationCache
VertexDeclarationCache(); VertexDeclarationCache();
~VertexDeclarationCache(); ~VertexDeclarationCache();
GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program); GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program, GLsizei instances);
void markStateDirty(); void markStateDirty();
...@@ -262,6 +262,7 @@ class VertexDeclarationCache ...@@ -262,6 +262,7 @@ class VertexDeclarationCache
VBData mAppliedVBs[MAX_VERTEX_ATTRIBS]; VBData mAppliedVBs[MAX_VERTEX_ATTRIBS];
IDirect3DVertexDeclaration9 *mLastSetVDecl; IDirect3DVertexDeclaration9 *mLastSetVDecl;
bool mInstancingEnabled;
struct VertexDeclCacheEntry struct VertexDeclCacheEntry
{ {
...@@ -452,10 +453,8 @@ class Context ...@@ -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 readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask); void clear(GLbitfield mask);
void drawArrays(GLenum mode, GLint first, GLsizei count); void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
void sync(bool block); // flush/finish void sync(bool block); // flush/finish
// Draw the last segment of a line loop // Draw the last segment of a line loop
...@@ -514,7 +513,7 @@ class Context ...@@ -514,7 +513,7 @@ class Context
bool applyRenderTarget(bool ignoreViewport); bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode); 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); GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders(); void applyShaders();
void applyTextures(); 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 // 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.
// //
...@@ -245,6 +245,8 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -245,6 +245,8 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
translated[i].vertexBuffer = vertexBuffer->getBuffer(); translated[i].vertexBuffer = vertexBuffer->getBuffer();
translated[i].serial = vertexBuffer->getSerial(); translated[i].serial = vertexBuffer->getSerial();
translated[i].divisor = attribs[i].mDivisor;
translated[i].type = converter.d3dDeclType; translated[i].type = converter.d3dDeclType;
translated[i].stride = converter.outputElementSize; translated[i].stride = converter.outputElementSize;
translated[i].offset = streamOffset; translated[i].offset = streamOffset;
...@@ -277,6 +279,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -277,6 +279,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
translated[i].serial = mCurrentValueBuffer[i]->getSerial(); translated[i].serial = mCurrentValueBuffer[i]->getSerial();
translated[i].divisor = 0;
translated[i].type = D3DDECLTYPE_FLOAT4; translated[i].type = D3DDECLTYPE_FLOAT4;
translated[i].stride = 0; 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 // 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.
// //
...@@ -31,6 +31,7 @@ struct TranslatedAttribute ...@@ -31,6 +31,7 @@ struct TranslatedAttribute
IDirect3DVertexBuffer9 *vertexBuffer; IDirect3DVertexBuffer9 *vertexBuffer;
unsigned int serial; unsigned int serial;
unsigned int divisor;
}; };
class VertexBuffer 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 // 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.
// //
...@@ -1943,7 +1943,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -1943,7 +1943,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
if (context) if (context)
{ {
context->drawArrays(mode, first, count); context->drawArrays(mode, first, count, 0);
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -1963,11 +1963,14 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun ...@@ -1963,11 +1963,14 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
gl::Context *context = gl::getNonLostContext(); if (primcount > 0)
if (context)
{ {
context->drawArraysInstanced(mode, first, count, primcount); gl::Context *context = gl::getNonLostContext();
if (context)
{
context->drawArrays(mode, first, count, primcount);
}
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -2007,7 +2010,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv ...@@ -2007,7 +2010,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
context->drawElements(mode, count, type, indices); context->drawElements(mode, count, type, indices, 0);
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -2028,26 +2031,29 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t ...@@ -2028,26 +2031,29 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
gl::Context *context = gl::getNonLostContext(); if (primcount > 0)
if (context)
{ {
switch (type) gl::Context *context = gl::getNonLostContext();
if (context)
{ {
case GL_UNSIGNED_BYTE: switch (type)
case GL_UNSIGNED_SHORT:
break;
case GL_UNSIGNED_INT:
if (!context->supports32bitIndices())
{ {
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: context->drawElements(mode, count, type, indices, primcount);
return error(GL_INVALID_ENUM);
} }
context->drawElementsInstanced(mode, count, type, indices, primcount);
} }
} }
catch(std::bad_alloc&) 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