Moves all GL draw commands to CDeviceCommandContext.

Differential Revision: https://code.wildfiregames.com/D4518
This was SVN commit r26525.
This commit is contained in:
Vladislav Belov 2022-03-03 07:09:59 +00:00
parent 7c3aed5f36
commit 3a4bbd11fd
27 changed files with 250 additions and 127 deletions

View File

@ -60,7 +60,7 @@ inline void DrawTextureImpl(
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, uvs.data());
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 2);
deviceCommandContext->Draw(0, vertices.size() / 2);
}
} // anonymous namespace
@ -253,7 +253,8 @@ void CCanvas2D::DrawLine(const std::vector<CVector2D>& points, const float width
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, uvs.data());
shader->AssertPointersBound();
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, indices.data());
m->DeviceCommandContext->SetIndexBufferData(indices.data());
m->DeviceCommandContext->DrawIndexed(0, indices.size(), 0);
}
void CCanvas2D::DrawRect(const CRect& rect, const CColor& color)

View File

@ -184,7 +184,7 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
g_Renderer.SetViewport(oldVp);

View File

@ -68,7 +68,9 @@ unsigned int ScaleColor(unsigned int color, float x)
return (0xff000000 | b | g << 8 | r << 16);
}
void DrawTexture(const CShaderProgramPtr& shader)
void DrawTexture(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const CShaderProgramPtr& shader)
{
const float quadUVs[] =
{
@ -95,7 +97,7 @@ void DrawTexture(const CShaderProgramPtr& shader)
shader->VertexPointer(3, GL_FLOAT, 0, quadVertices);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
}
struct MinimapUnitVertex
@ -387,7 +389,7 @@ void CMiniMapTexture::RenderFinalTexture(
shader->Uniform(str_textureTransform, terrainTransform);
if (m_TerrainTexture)
DrawTexture(shader);
DrawTexture(deviceCommandContext, shader);
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
@ -409,7 +411,7 @@ void CMiniMapTexture::RenderFinalTexture(
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, territoryTexture.GetMinimapTextureMatrix());
DrawTexture(shader);
DrawTexture(deviceCommandContext, shader);
pipelineStateDesc.blendState.enabled = false;
pipelineStateDesc.blendState.colorWriteMask =
@ -420,7 +422,7 @@ void CMiniMapTexture::RenderFinalTexture(
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, losTexture.GetMinimapTextureMatrix());
DrawTexture(shader);
DrawTexture(deviceCommandContext, shader);
tech->EndPass();
@ -528,7 +530,7 @@ void CMiniMapTexture::RenderFinalTexture(
scissorRect.width = scissorRect.height = FINAL_TEXTURE_SIZE - 2;
deviceCommandContext->SetScissors(1, &scissorRect);
u8* indexBase = m_IndexArray.Bind(deviceCommandContext);
m_IndexArray.UploadIfNeeded(deviceCommandContext);
u8* base = m_VertexArray.Bind(deviceCommandContext);
const GLsizei stride = (GLsizei)m_VertexArray.GetStride();
@ -536,7 +538,8 @@ void CMiniMapTexture::RenderFinalTexture(
shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
shader->AssertPointersBound();
glDrawElements(GL_TRIANGLES, m_EntitiesDrawn * 6, GL_UNSIGNED_SHORT, indexBase);
deviceCommandContext->SetIndexBuffer(m_IndexArray.GetBuffer());
deviceCommandContext->DrawIndexed(m_IndexArray.GetOffset(), m_EntitiesDrawn * 6, 0);
g_Renderer.GetStats().m_DrawCalls++;
CVertexBuffer::Unbind(deviceCommandContext);

View File

@ -200,12 +200,10 @@ void CParticleEmitter::RenderArray(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const CShaderProgramPtr& shader)
{
// Some drivers apparently don't like count=0 in glDrawArrays here,
// so skip all drawing in that case
if (m_Particles.empty())
return;
u8* indexBase = m_IndexArray.Bind(deviceCommandContext);
m_IndexArray.UploadIfNeeded(deviceCommandContext);
u8* base = m_VertexArray.Bind(deviceCommandContext);
GLsizei stride = (GLsizei)m_VertexArray.GetStride();
@ -220,7 +218,9 @@ void CParticleEmitter::RenderArray(
shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
shader->AssertPointersBound();
glDrawElements(GL_TRIANGLES, (GLsizei)(m_Particles.size() * 6), GL_UNSIGNED_SHORT, indexBase);
deviceCommandContext->SetIndexBuffer(m_IndexArray.GetBuffer());
deviceCommandContext->DrawIndexed(m_IndexArray.GetOffset(), m_Particles.size() * 6, 0);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_Particles += m_Particles.size();

View File

@ -182,7 +182,7 @@ public:
/**
* Checks that all the required vertex attributes have been set.
* Call this before calling glDrawArrays/glDrawElements etc to avoid potential crashes.
* Call this before calling Draw/DrawIndexed etc to avoid potential crashes.
*/
void AssertPointersBound();

View File

@ -263,13 +263,14 @@ void CTextRenderer::Render(
size_t idx = 0;
auto flush = [&idx, &vertexes, &indexes, &shader]() -> void {
auto flush = [deviceCommandContext, &idx, &vertexes, &indexes, &shader]() -> void {
if (idx == 0)
return;
shader->VertexPointer(2, GL_SHORT, sizeof(t2f_v2i), &vertexes[0].x);
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, sizeof(t2f_v2i), &vertexes[0].u);
glDrawElements(GL_TRIANGLES, idx * 6, GL_UNSIGNED_SHORT, &indexes[0]);
deviceCommandContext->SetIndexBufferData(indexes.data());
deviceCommandContext->DrawIndexed(0, idx * 6, 0);
idx = 0;
};

View File

@ -95,7 +95,9 @@ void CropPointsByCircle(const std::array<CVector3D, 4>& points, const CVector3D&
}
}
void DrawTexture(CShaderProgramPtr shader, float angle, float x, float y, float x2, float y2, float mapScale)
void DrawTexture(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const CShaderProgramPtr& shader, float angle, float x, float y, float x2, float y2, float mapScale)
{
// Rotate the texture coordinates (0,0)-(coordMax,coordMax) around their center point (m,m)
// Scale square maps to fit in circular minimap area
@ -126,7 +128,7 @@ void DrawTexture(CShaderProgramPtr shader, float angle, float x, float y, float
shader->VertexPointer(3, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
}
} // anonymous namespace
@ -422,7 +424,9 @@ void CMiniMap::Draw(CCanvas2D& canvas)
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
tech->BeginPass();
g_Renderer.GetDeviceCommandContext()->SetGraphicsPipelineState(pipelineStateDesc);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
shader = tech->GetShader();
shader->BindTexture(str_baseTex, miniMapTexture.GetTexture());
@ -435,7 +439,7 @@ void CMiniMap::Draw(CCanvas2D& canvas)
const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
const float angle = GetAngle();
DrawTexture(shader, angle, x, y, x2, y2, m_MapScale);
DrawTexture(deviceCommandContext, shader, angle, x, y, x2, y2, m_MapScale);
tech->EndPass();
}

View File

@ -86,7 +86,10 @@ void CDebugRenderer::DrawLine(
CShaderTechniquePtr debugLineTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
debugLineTech->BeginPass();
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugLineTech, color, depthTestEnabled);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
deviceCommandContext, debugLineTech, color, depthTestEnabled);
const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -125,7 +128,7 @@ void CDebugRenderer::DrawLine(
debugLineShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
debugLineShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
debugLineTech->EndPass();
#endif
@ -140,7 +143,10 @@ void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, con
CShaderTechniquePtr debugCircleTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
debugCircleTech->BeginPass();
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugCircleTech, color);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
deviceCommandContext, debugCircleTech, color);
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -173,7 +179,7 @@ void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, con
debugCircleShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
debugCircleShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
debugCircleTech->EndPass();
#endif
@ -199,7 +205,10 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
CShaderTechniquePtr overlayTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
overlayTech->BeginPass();
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), overlayTech, color, true, wireframe);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
deviceCommandContext, overlayTech, color, true, wireframe);
CShaderProgramPtr overlayShader = overlayTech->GetShader();
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
@ -246,7 +255,7 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
overlayShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
overlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
vertices.clear();
@ -264,7 +273,7 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
overlayShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
overlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
#undef ADD
overlayTech->EndPass();
@ -286,8 +295,10 @@ void CDebugRenderer::DrawBoundingBox(
{
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
shaderTech->BeginPass();
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
g_Renderer.GetDeviceCommandContext(), shaderTech, color, true, wireframe);
deviceCommandContext, shaderTech, color, true, wireframe);
const CShaderProgramPtr& shader = shaderTech->GetShader();
shader->Uniform(str_color, color);
@ -317,7 +328,7 @@ void CDebugRenderer::DrawBoundingBox(
shader->VertexPointer(3, GL_FLOAT, 3 * sizeof(float), data.data());
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6*6);
deviceCommandContext->Draw(0, 6*6);
shaderTech->EndPass();
}
@ -326,8 +337,10 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wi
{
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
shaderTech->BeginPass();
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
g_Renderer.GetDeviceCommandContext(), shaderTech, color, true, wireframe);
deviceCommandContext, shaderTech, color, true, wireframe);
const CShaderProgramPtr& shader = shaderTech->GetShader();
shader->Uniform(str_color, color);
@ -361,7 +374,7 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wi
shader->VertexPointer(3, GL_FLOAT, 3 * sizeof(float), data.data());
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, data.size() / 5);
deviceCommandContext->Draw(0, data.size() / 5);
shaderTech->EndPass();
}

View File

@ -211,11 +211,11 @@ void CDecalRData::RenderDecals(
if (lastIB != batch.indices->m_Owner)
{
lastIB = batch.indices->m_Owner;
batch.indices->m_Owner->Bind(deviceCommandContext);
batch.indices->m_Owner->UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(batch.indices->m_Owner->GetBuffer());
}
u8* indexBase = nullptr;
glDrawElements(GL_TRIANGLES, batch.indices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16) * (batch.indices->m_Index));
deviceCommandContext->DrawIndexed(batch.indices->m_Index, batch.indices->m_Count, 0);
// bump stats
g_Renderer.m_Stats.m_DrawCalls++;

View File

@ -221,7 +221,8 @@ void ShaderModelVertexRenderer::RenderModel(
u8* base = shadermodel->m_Array.Bind(deviceCommandContext);
GLsizei stride = (GLsizei)shadermodel->m_Array.GetStride();
u8* indexBase = m->shadermodeldef->m_IndexArray.Bind(deviceCommandContext);
m->shadermodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer());
if (streamflags & STREAM_POS)
shader->VertexPointer(3, GL_FLOAT, stride, base + shadermodel->m_Position.offset);
@ -231,19 +232,14 @@ void ShaderModelVertexRenderer::RenderModel(
shader->AssertPointersBound();
// render the lot
size_t numFaces = mdldef->GetNumFaces();
// Render the lot.
const size_t numberOfFaces = mdldef->GetNumFaces();
// Draw with DrawRangeElements where available, since it might be more efficient
#if CONFIG2_GLES
glDrawElements(GL_TRIANGLES, (GLsizei)numFaces*3, GL_UNSIGNED_SHORT, indexBase);
#else
glDrawRangeElementsEXT(GL_TRIANGLES, 0, (GLuint)mdldef->GetNumVertices()-1,
(GLsizei)numFaces*3, GL_UNSIGNED_SHORT, indexBase);
#endif
deviceCommandContext->DrawIndexedInRange(
m->shadermodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, mdldef->GetNumVertices() - 1);
// bump stats
// Bump stats.
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_ModelTris += numFaces;
g_Renderer.m_Stats.m_ModelTris += numberOfFaces;
}

View File

@ -327,7 +327,8 @@ void InstancingModelRenderer::PrepareModelDef(
u8* base = m->imodeldef->m_Array.Bind(deviceCommandContext);
GLsizei stride = (GLsizei)m->imodeldef->m_Array.GetStride();
m->imodeldefIndexBase = m->imodeldef->m_IndexArray.Bind(deviceCommandContext);
m->imodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(m->imodeldef->m_IndexArray.GetBuffer());
if (streamflags & STREAM_POS)
shader->VertexPointer(3, GL_FLOAT, stride, base + m->imodeldef->m_Position.offset);
@ -361,7 +362,7 @@ void InstancingModelRenderer::PrepareModelDef(
// Render one model
void InstancingModelRenderer::RenderModel(
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext),
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const CShaderProgramPtr& shader, int UNUSED(streamflags), CModel* model, CModelRData* UNUSED(data))
{
const CModelDefPtr& mdldef = model->GetModelDef();
@ -377,19 +378,14 @@ void InstancingModelRenderer::RenderModel(
shader->Uniform(str_skinBlendMatrices, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices());
}
// render the lot
size_t numFaces = mdldef->GetNumFaces();
// Render the lot.
const size_t numberOfFaces = mdldef->GetNumFaces();
// Draw with DrawRangeElements where available, since it might be more efficient
#if CONFIG2_GLES
glDrawElements(GL_TRIANGLES, (GLsizei)numFaces*3, GL_UNSIGNED_SHORT, m->imodeldefIndexBase);
#else
glDrawRangeElementsEXT(GL_TRIANGLES, 0, (GLuint)m->imodeldef->m_Array.GetNumberOfVertices()-1,
(GLsizei)numFaces*3, GL_UNSIGNED_SHORT, m->imodeldefIndexBase);
#endif
deviceCommandContext->DrawIndexedInRange(
m->imodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, m->imodeldef->m_Array.GetNumberOfVertices() - 1);
// bump stats
// Bump stats.
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_ModelTris += numFaces;
g_Renderer.m_Stats.m_ModelTris += numberOfFaces;
}

View File

@ -548,11 +548,12 @@ void OverlayRenderer::RenderQuadOverlays(
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
// Base offsets (in bytes) of the two backing stores relative to their owner VBO
u8* indexBase = m->quadIndices.Bind(deviceCommandContext);
m->quadIndices.UploadIfNeeded(deviceCommandContext);
u8* vertexBase = m->quadVertices.Bind(deviceCommandContext);
GLsizei indexStride = m->quadIndices.GetStride();
GLsizei vertexStride = m->quadVertices.GetStride();
deviceCommandContext->SetIndexBuffer(m->quadIndices.GetBuffer());
for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); ++it)
{
QuadBatchData& batchRenderData = it->second;
@ -584,7 +585,7 @@ void OverlayRenderer::RenderQuadOverlays(
shader->ColorPointer(m->quadAttributeColor.elems, m->quadAttributeColor.type, vertexStride, vertexBase + m->quadAttributeColor.offset);
shader->AssertPointersBound();
glDrawElements(GL_TRIANGLES, (GLsizei)(batchNumQuads * 6), GL_UNSIGNED_SHORT, indexBase + indexStride * batchRenderData.m_IndicesBase);
deviceCommandContext->DrawIndexed(m->quadIndices.GetOffset() + batchRenderData.m_IndicesBase, batchNumQuads * 6, 0);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_OverlayTris += batchNumQuads*2;
@ -668,7 +669,7 @@ void OverlayRenderer::RenderForegroundOverlays(
shader->VertexPointer(3, GL_FLOAT, sizeof(CVector3D), &position[0].X);
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_OverlayTris += 2;
@ -788,7 +789,8 @@ void OverlayRenderer::RenderSphereOverlays(
shader->Uniform(str_color, sphere->m_Color);
glDrawElements(GL_TRIANGLES, m->sphereIndexes.size(), GL_UNSIGNED_SHORT, &m->sphereIndexes[0]);
deviceCommandContext->SetIndexBufferData(m->sphereIndexes.data());
deviceCommandContext->DrawIndexed(0, m->sphereIndexes.size(), 0);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_OverlayTris = m->sphereIndexes.size()/3;

View File

@ -669,8 +669,6 @@ void CPatchRData::Update(CSimulation2* simulation)
}
}
// Types used for glMultiDrawElements batching:
// To minimise the cost of memory allocations, everything used for computing
// batches uses a arena allocator. (All allocations are short-lived so we can
// just throw away the whole arena at the end of each frame.)
@ -702,7 +700,7 @@ typename M::mapped_type& PooledPairGet(M& m, const typename M::key_type& k, Aren
}
// Each multidraw batch has a list of index counts, and a list of pointers-to-first-indexes
using BatchElements = std::pair<std::vector<GLint, ProxyAllocator<GLint, Arena>>, std::vector<void*, ProxyAllocator<void*, Arena>>>;
using BatchElements = std::pair<std::vector<GLint, ProxyAllocator<GLint, Arena>>, std::vector<u32, ProxyAllocator<u32, Arena>>>;
// Group batches by index buffer
using IndexBufferBatches = PooledBatchMap<CVertexBuffer*, BatchElements>;
@ -760,8 +758,7 @@ void CPatchRData::RenderBases(
batch.first.push_back(splat.m_IndexCount);
u8* indexBase = nullptr;
batch.second.push_back(indexBase + sizeof(u16)*(patch->m_VBBaseIndices->m_Index + splat.m_IndexStart));
batch.second.push_back(patch->m_VBBaseIndices->m_Index + splat.m_IndexStart);
}
}
@ -814,15 +811,13 @@ void CPatchRData::RenderBases(
for (IndexBufferBatches::iterator it = itv->second.begin(); it != itv->second.end(); ++it)
{
it->first->Bind(deviceCommandContext);
it->first->UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(it->first->GetBuffer());
BatchElements& batch = it->second;
// Don't use glMultiDrawElements here since it doesn't have a significant
// performance impact and it suffers from various driver bugs (e.g. it breaks
// in Mesa 7.10 swrast with index VBOs)
for (size_t i = 0; i < batch.first.size(); ++i)
glDrawElements(GL_TRIANGLES, batch.first[i], GL_UNSIGNED_SHORT, batch.second[i]);
deviceCommandContext->DrawIndexed(batch.second[i], batch.first[i], 0);
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris += std::accumulate(batch.first.begin(), batch.first.end(), 0) / 3;
@ -928,8 +923,7 @@ void CPatchRData::RenderBlends(
BatchElements& batch = PooledPairGet(PooledMapGet(batches.back().m_Batches, vertices->m_Owner, arena), indices->m_Owner, arena);
batch.first.push_back(splats.back().m_IndexCount);
u8* indexBase = nullptr;
batch.second.push_back(indexBase + sizeof(u16)*(indices->m_Index + splats.back().m_IndexStart));
batch.second.push_back(indices->m_Index + splats.back().m_IndexStart);
splats.pop_back();
}
@ -1045,12 +1039,13 @@ void CPatchRData::RenderBlends(
for (IndexBufferBatches::iterator it = itv->second.begin(); it != itv->second.end(); ++it)
{
it->first->Bind(deviceCommandContext);
it->first->UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(it->first->GetBuffer());
BatchElements& batch = it->second;
for (size_t i = 0; i < batch.first.size(); ++i)
glDrawElements(GL_TRIANGLES, batch.first[i], GL_UNSIGNED_SHORT, batch.second[i]);
deviceCommandContext->DrawIndexed(batch.second[i], batch.first[i], 0);
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_BlendSplats++;
@ -1072,13 +1067,13 @@ void CPatchRData::RenderStreams(
PROFILE3("render terrain streams");
// Each batch has a list of index counts, and a list of pointers-to-first-indexes
using StreamBatchElements = std::pair<std::vector<GLint>, std::vector<void*> > ;
using StreamBatchElements = std::pair<std::vector<GLint>, std::vector<u32>>;
// Group batches by index buffer
using StreamIndexBufferBatches = std::map<CVertexBuffer*, StreamBatchElements> ;
using StreamIndexBufferBatches = std::map<CVertexBuffer*, StreamBatchElements>;
// Group batches by vertex buffer
using StreamVertexBufferBatches = std::map<CVertexBuffer*, StreamIndexBufferBatches> ;
using StreamVertexBufferBatches = std::map<CVertexBuffer*, StreamIndexBufferBatches>;
StreamVertexBufferBatches batches;
@ -1091,8 +1086,7 @@ void CPatchRData::RenderStreams(
batch.first.push_back(patch->m_VBBaseIndices->m_Count);
u8* indexBase = nullptr;
batch.second.push_back(indexBase + sizeof(u16)*(patch->m_VBBaseIndices->m_Index));
batch.second.push_back(patch->m_VBBaseIndices->m_Index);
}
PROFILE_END("compute batches");
@ -1115,12 +1109,13 @@ void CPatchRData::RenderStreams(
for (const std::pair<CVertexBuffer* const, StreamBatchElements>& batchIndexBuffer : streamBatch.second)
{
batchIndexBuffer.first->Bind(deviceCommandContext);
batchIndexBuffer.first->UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(batchIndexBuffer.first->GetBuffer());
const StreamBatchElements& batch = batchIndexBuffer.second;
for (size_t i = 0; i < batch.first.size(); ++i)
glDrawElements(GL_TRIANGLES, batch.first[i], GL_UNSIGNED_SHORT, batch.second[i]);
deviceCommandContext->DrawIndexed(batch.second[i], batch.first[i], 0);
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris += std::accumulate(batch.first.begin(), batch.first.end(), 0) / 3;
@ -1187,7 +1182,7 @@ void CPatchRData::RenderSides(
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, patch->m_VBSides->m_Index, (GLsizei)patch->m_VBSides->m_Count);
deviceCommandContext->Draw(patch->m_VBSides->m_Index, (GLsizei)patch->m_VBSides->m_Count);
// bump stats
g_Renderer.m_Stats.m_DrawCalls++;
@ -1433,6 +1428,8 @@ void CPatchRData::RenderWaterSurface(
if (!m_VBWater)
return;
m_VBWaterIndices->m_Owner->UploadIfNeeded(deviceCommandContext);
SWaterVertex* base = reinterpret_cast<SWaterVertex*>(m_VBWater->m_Owner->Bind(deviceCommandContext));
// Setup data pointers.
@ -1443,10 +1440,8 @@ void CPatchRData::RenderWaterSurface(
shader->AssertPointersBound();
u8* indexBase = m_VBWaterIndices->m_Owner->Bind(deviceCommandContext);
glDrawElements(
GL_TRIANGLES, static_cast<GLsizei>(m_VBWaterIndices->m_Count),
GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndices->m_Index));
deviceCommandContext->SetIndexBuffer(m_VBWaterIndices->m_Owner->GetBuffer());
deviceCommandContext->DrawIndexed(m_VBWaterIndices->m_Index, m_VBWaterIndices->m_Count, 0);
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_WaterTris += m_VBWaterIndices->m_Count / 3;
@ -1463,6 +1458,8 @@ void CPatchRData::RenderWaterShore(
if (!m_VBWaterShore)
return;
m_VBWaterIndicesShore->m_Owner->UploadIfNeeded(deviceCommandContext);
SWaterVertex* base = reinterpret_cast<SWaterVertex*>(m_VBWaterShore->m_Owner->Bind(deviceCommandContext));
const GLsizei stride = sizeof(SWaterVertex);
@ -1471,9 +1468,8 @@ void CPatchRData::RenderWaterShore(
shader->AssertPointersBound();
u8* indexBase = m_VBWaterIndicesShore->m_Owner->Bind(deviceCommandContext);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_VBWaterIndicesShore->m_Count),
GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndicesShore->m_Index));
deviceCommandContext->SetIndexBuffer(m_VBWaterIndicesShore->m_Owner->GetBuffer());
deviceCommandContext->DrawIndexed(m_VBWaterIndicesShore->m_Index, m_VBWaterIndicesShore->m_Count, 0);
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_WaterTris += m_VBWaterIndicesShore->m_Count / 3;

View File

@ -231,7 +231,7 @@ void CPostprocManager::ApplyBlurDownscale2x(
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
g_Renderer.SetViewport(oldVp);
@ -287,7 +287,7 @@ void CPostprocManager::ApplyBlurGauss(
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
g_Renderer.SetViewport(oldVp);
@ -312,7 +312,7 @@ void CPostprocManager::ApplyBlurGauss(
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
g_Renderer.SetViewport(oldVp);
@ -432,7 +432,7 @@ void CPostprocManager::ApplyEffect(
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
shaderTech->EndPass(pass);

View File

@ -750,7 +750,7 @@ void ShadowMap::RenderDebugTexture(
texShader->VertexPointer(2, GL_FLOAT, 0, boxVerts);
texShader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, boxUV);
texShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
texTech->EndPass();

View File

@ -494,7 +494,7 @@ void SilhouetteRenderer::RenderDebugOverlays(
r.x0, r.y1,
};
shader->VertexPointer(2, GL_SHORT, 0, verts);
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
}
shaderTech->EndPass();

View File

@ -248,7 +248,7 @@ void SkyManager::RenderSky(
GL_TEXTURE0, 3, GL_FLOAT, stride, base + m_AttributeUV.offset);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, m_VertexArray.GetNumberOfVertices());
deviceCommandContext->Draw(0, m_VertexArray.GetNumberOfVertices());
skytech->EndPass();
#endif

View File

@ -232,7 +232,7 @@ void TerrainOverlay::RenderTile(
overlayShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
overlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
overlayTech->EndPass();
#endif
@ -300,7 +300,7 @@ void TerrainOverlay::RenderTileOutline(
overlayShader->VertexPointer(3, GL_FLOAT, 0, vertices.data());
overlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
deviceCommandContext->Draw(0, vertices.size() / 3);
overlayTech->EndPass();
#endif

View File

@ -212,7 +212,7 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
debugOverlayShader->TexCoordPointer(GL_TEXTURE0, 3, GL_FLOAT, stride, waterPos);
debugOverlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
deviceCommandContext->Draw(0, 6);
}
debugOverlayTech->EndPass();

View File

@ -48,6 +48,9 @@ void CTexturedLineRData::Render(
line.m_TextureBase->UploadBackendTextureIfNeeded(deviceCommandContext);
line.m_TextureMask->UploadBackendTextureIfNeeded(deviceCommandContext);
m_VBIndices->m_Owner->UploadIfNeeded(deviceCommandContext);
shader->BindTexture(str_baseTex, line.m_TextureBase->GetBackendTexture());
shader->BindTexture(str_maskTex, line.m_TextureMask->GetBackendTexture());
shader->Uniform(str_objectColor, line.m_Color);
@ -65,10 +68,10 @@ void CTexturedLineRData::Render(
if (streamFlags & STREAM_UV1)
shader->TexCoordPointer(GL_TEXTURE1, 2, GL_FLOAT, stride, &vertexBase->m_UVs[0]);
u8* indexBase = m_VBIndices->m_Owner->Bind(deviceCommandContext);
shader->AssertPointersBound();
glDrawElements(GL_TRIANGLES, m_VBIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*m_VBIndices->m_Index);
deviceCommandContext->SetIndexBuffer(m_VBIndices->m_Owner->GetBuffer());
deviceCommandContext->DrawIndexed(m_VBIndices->m_Index, m_VBIndices->m_Count, 0);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_OverlayTris += m_VBIndices->m_Count/3;

View File

@ -291,13 +291,20 @@ u8* VertexArray::Bind(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
if (!m_VB)
return NULL;
return nullptr;
u8* base = m_VB->m_Owner->Bind(deviceCommandContext);
base += m_VB->m_Index*m_Stride;
UploadIfNeeded(deviceCommandContext);
m_VB->m_Owner->Bind(deviceCommandContext);
u8* base = nullptr;
base += m_VB->m_Index * m_Stride;
return base;
}
void VertexArray::UploadIfNeeded(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
m_VB->m_Owner->UploadIfNeeded(deviceCommandContext);
}
// Free the backing store to save some memory
void VertexArray::FreeBackingStore()

View File

@ -179,17 +179,22 @@ public:
// All vertex data is lost when a vertex array is re-layouted.
void Layout();
// (Re-)Upload the attributes of the vertex array from the backing store to
// the underlying VBO object.
// the underlying buffer.
void Upload();
// Make this vertex array's data available for the next series of calls to Bind
void PrepareForRendering();
// Bind this array, returns the base address for calls to glVertexPointer etc.
u8* Bind(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
void UploadIfNeeded(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
// If you know for certain that you'll never have to change the data again,
// call this to free some memory.
void FreeBackingStore();
Renderer::Backend::GL::CBuffer* GetBuffer() { return m_VB ? m_VB->m_Owner->GetBuffer() : nullptr; }
uint32_t GetOffset() const { return m_VB ? m_VB->m_Index : 0; }
private:
void Free();
@ -212,9 +217,7 @@ private:
/**
* A VertexArray that is specialised to handle 16-bit array indices.
* Call Bind() and pass the return value to the indices parameter of
* glDrawElements/glDrawRangeElements/glMultiDrawElements.
* Use CVertexBuffer::Unbind() to unbind the array when done.
* Call UploadIfNeeded() before use in Draw/DrawIndexed.
*/
class VertexIndexArray : public VertexArray
{

View File

@ -59,6 +59,10 @@ CVertexBuffer::CVertexBuffer(
// address at most 64K of them with 16-bit indices
size = std::min(size, vertexSize * 65536);
}
else if (type == Renderer::Backend::GL::CBuffer::Type::INDEX)
{
ENSURE(vertexSize == sizeof(u16));
}
// store max/free vertex counts
m_MaxVertices = m_FreeVertices = size / vertexSize;
@ -222,19 +226,13 @@ void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)
}
}
///////////////////////////////////////////////////////////////////////////////
// Bind: bind to this buffer; return pointer to address required as parameter
// to glVertexPointer ( + etc) calls
u8* CVertexBuffer::Bind(
void CVertexBuffer::UploadIfNeeded(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
if (UseStreaming(m_Buffer->IsDynamic()))
{
if (!m_HasNeededChunks)
{
deviceCommandContext->BindBuffer(m_Buffer->GetType(), m_Buffer.get());
return nullptr;
}
return;
// If any chunks are out of sync with the current VBO, and are
// needed for rendering this frame, we'll need to re-upload the VBO
@ -290,8 +288,15 @@ u8* CVertexBuffer::Bind(
m_HasNeededChunks = false;
}
deviceCommandContext->BindBuffer(m_Buffer->GetType(), m_Buffer.get());
}
// Bind: bind to this buffer; return pointer to address required as parameter
// to glVertexPointer ( + etc) calls
u8* CVertexBuffer::Bind(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
UploadIfNeeded(deviceCommandContext);
deviceCommandContext->BindBuffer(m_Buffer->GetType(), m_Buffer.get());
return nullptr;
}

View File

@ -102,6 +102,8 @@ public:
/// to glVertexPointer ( + etc) calls
u8* Bind(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
void UploadIfNeeded(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
/// Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it
static void Unbind(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
@ -135,6 +137,8 @@ public:
*/
static bool UseStreaming(const bool dynamic);
Renderer::Backend::GL::CBuffer* GetBuffer() { return m_Buffer.get(); }
private:
friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager

View File

@ -812,9 +812,9 @@ void WaterManager::RenderWaves(
shader->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff);
shader->Uniform(str_width, (int)m_ShoreWaves[a]->m_Width);
u8* indexBase = m_ShoreWavesVBIndices->m_Owner->Bind(deviceCommandContext);
glDrawElements(GL_TRIANGLES, (GLsizei) (m_ShoreWaves[a]->m_Width-1)*(7*6),
GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_ShoreWavesVBIndices->m_Index));
m_ShoreWavesVBIndices->m_Owner->UploadIfNeeded(deviceCommandContext);
deviceCommandContext->SetIndexBuffer(m_ShoreWavesVBIndices->m_Owner->GetBuffer());
deviceCommandContext->DrawIndexed(m_ShoreWavesVBIndices->m_Index, (m_ShoreWaves[a]->m_Width - 1) * (7 * 6), 0);
shader->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff + 6.0f);

View File

@ -379,7 +379,13 @@ void CDeviceCommandContext::BindTexture(const uint32_t unit, const GLenum target
void CDeviceCommandContext::BindBuffer(const CBuffer::Type type, CBuffer* buffer)
{
ENSURE(!buffer || type == buffer->GetType());
ENSURE(!buffer || buffer->GetType() == type);
if (type == CBuffer::Type::INDEX)
{
if (!buffer)
m_IndexBuffer = nullptr;
m_IndexBufferData = nullptr;
}
glBindBufferARB(BufferTypeToGLTarget(type), buffer ? buffer->GetHandle() : 0);
}
@ -387,7 +393,12 @@ void CDeviceCommandContext::Flush()
{
ResetStates();
m_IndexBuffer = nullptr;
m_IndexBufferData = nullptr;
BindTexture(0, GL_TEXTURE_2D, 0);
BindBuffer(CBuffer::Type::INDEX, nullptr);
BindBuffer(CBuffer::Type::VERTEX, nullptr);
ENSURE(m_ScopedLabelDepth == 0);
}
@ -711,6 +722,70 @@ void CDeviceCommandContext::SetViewports(const uint32_t viewportCount, const Rec
glViewport(viewports[0].x, viewports[0].y, viewports[0].width, viewports[0].height);
}
void CDeviceCommandContext::SetIndexBuffer(CBuffer* buffer)
{
ENSURE(buffer->GetType() == CBuffer::Type::INDEX);
m_IndexBuffer = buffer;
m_IndexBufferData = nullptr;
BindBuffer(CBuffer::Type::INDEX, m_IndexBuffer);
}
void CDeviceCommandContext::SetIndexBufferData(const void* data)
{
if (m_IndexBuffer)
{
BindBuffer(CBuffer::Type::INDEX, nullptr);
m_IndexBuffer = nullptr;
}
m_IndexBufferData = data;
}
void CDeviceCommandContext::Draw(
const uint32_t firstVertex, const uint32_t vertexCount)
{
// Some drivers apparently don't like count = 0 in glDrawArrays here, so skip
// all drawing in that case.
if (vertexCount == 0)
return;
glDrawArrays(GL_TRIANGLES, firstVertex, vertexCount);
}
void CDeviceCommandContext::DrawIndexed(
const uint32_t firstIndex, const uint32_t indexCount, const int32_t vertexOffset)
{
if (indexCount == 0)
return;
ENSURE(m_IndexBuffer || m_IndexBufferData);
ENSURE(vertexOffset == 0);
if (m_IndexBuffer)
{
ENSURE(sizeof(uint16_t) * (firstIndex + indexCount) <= m_IndexBuffer->GetSize());
}
// Don't use glMultiDrawElements here since it doesn't have a significant
// performance impact and it suffers from various driver bugs (e.g. it breaks
// in Mesa 7.10 swrast with index VBOs).
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT,
static_cast<const void*>((static_cast<const uint8_t*>(m_IndexBufferData) + sizeof(uint16_t) * firstIndex)));
}
void CDeviceCommandContext::DrawIndexedInRange(
const uint32_t firstIndex, const uint32_t indexCount,
const uint32_t start, const uint32_t end)
{
if (indexCount == 0)
return;
ENSURE(m_IndexBuffer || m_IndexBufferData);
const void* indices =
static_cast<const void*>((static_cast<const uint8_t*>(m_IndexBufferData) + sizeof(uint16_t) * firstIndex));
// Draw with DrawRangeElements where available, since it might be more
// efficient for slow hardware.
#if CONFIG2_GLES
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, indices);
#else
glDrawRangeElementsEXT(GL_TRIANGLES, start, end, indexCount, GL_UNSIGNED_SHORT, indices);
#endif
}
CDeviceCommandContext::ScopedBind::ScopedBind(
CDeviceCommandContext* deviceCommandContext,
const GLenum target, const GLuint handle)

View File

@ -85,6 +85,17 @@ public:
void SetScissors(const uint32_t scissorCount, const Rect* scissors);
void SetViewports(const uint32_t viewportCount, const Rect* viewports);
void SetIndexBuffer(CBuffer* buffer);
void SetIndexBufferData(const void* data);
void Draw(const uint32_t firstVertex, const uint32_t vertexCount);
void DrawIndexed(
const uint32_t firstIndex, const uint32_t indexCount, const int32_t vertexOffset);
// TODO: should be removed when performance impact is minimal on slow hardware.
void DrawIndexedInRange(
const uint32_t firstIndex, const uint32_t indexCount,
const uint32_t start, const uint32_t end);
void BeginScopedLabel(const char* name);
void EndScopedLabel();
@ -116,6 +127,9 @@ private:
uint32_t m_ScopedLabelDepth = 0;
CBuffer* m_IndexBuffer = nullptr;
const void* m_IndexBufferData = nullptr;
uint32_t m_ActiveTextureUnit = 0;
using BindUnit = std::pair<GLenum, GLuint>;
std::array<BindUnit, 16> m_BoundTextures;