Index: ps/trunk/source/graphics/Canvas2D.cpp =================================================================== --- ps/trunk/source/graphics/Canvas2D.cpp +++ ps/trunk/source/graphics/Canvas2D.cpp @@ -56,10 +56,16 @@ shader->Uniform(str_colorAdd, add); shader->Uniform(str_colorMul, multiply); shader->Uniform(str_grayscaleFactor, grayscaleFactor); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, vertices.data()); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, uvs.data()); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, vertices.data()); + deviceCommandContext->SetVertexBufferData(1, uvs.data()); deviceCommandContext->Draw(0, vertices.size() / 2); } @@ -250,10 +256,16 @@ shader->Uniform(str_colorAdd, CColor(0.0f, 0.0f, 0.0f, 0.0f)); shader->Uniform(str_colorMul, color); shader->Uniform(str_grayscaleFactor, 0.0f); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, vertices.data()); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, uvs.data()); + + m->DeviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + m->DeviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + m->DeviceCommandContext->SetVertexBufferData(0, vertices.data()); + m->DeviceCommandContext->SetVertexBufferData(1, uvs.data()); m->DeviceCommandContext->SetIndexBufferData(indices.data()); m->DeviceCommandContext->DrawIndexed(0, indices.size(), 0); Index: ps/trunk/source/graphics/LOSTexture.cpp =================================================================== --- ps/trunk/source/graphics/LOSTexture.cpp +++ ps/trunk/source/graphics/LOSTexture.cpp @@ -181,8 +181,17 @@ 1.0f, 0.0f, 1.0f, 1.0f }; - shader->TexCoordPointer(GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer(Renderer::Backend::Format::R32G32_SFLOAT, 0, quadVerts); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); + deviceCommandContext->Draw(0, 6); g_Renderer.SetViewport(oldVp); Index: ps/trunk/source/graphics/MiniMapTexture.cpp =================================================================== --- ps/trunk/source/graphics/MiniMapTexture.cpp +++ ps/trunk/source/graphics/MiniMapTexture.cpp @@ -71,8 +71,7 @@ } void DrawTexture( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader) + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { const float quadUVs[] = { @@ -95,10 +94,15 @@ -1.0f, -1.0f, 0.0f }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadUVs); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, quadVertices); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVertices); + deviceCommandContext->SetVertexBufferData(1, quadUVs); deviceCommandContext->Draw(0, 6); } @@ -390,7 +394,7 @@ shader->Uniform(str_textureTransform, terrainTransform); if (m_TerrainTexture) - DrawTexture(deviceCommandContext, shader); + DrawTexture(deviceCommandContext); deviceCommandContext->EndPass(); pipelineStateDesc.blendState.enabled = true; @@ -414,7 +418,7 @@ shader->Uniform(str_transform, baseTransform); shader->Uniform(str_textureTransform, territoryTexture.GetMinimapTextureMatrix()); - DrawTexture(deviceCommandContext, shader); + DrawTexture(deviceCommandContext); deviceCommandContext->EndPass(); pipelineStateDesc.blendState.enabled = false; @@ -427,7 +431,7 @@ shader->Uniform(str_transform, baseTransform); shader->Uniform(str_textureTransform, losTexture.GetMinimapTextureMatrix()); - DrawTexture(deviceCommandContext, shader); + DrawTexture(deviceCommandContext); deviceCommandContext->EndPass(); @@ -565,20 +569,25 @@ scissorRect.width = scissorRect.height = FINAL_TEXTURE_SIZE - 2; deviceCommandContext->SetScissors(1, &scissorRect); + m_VertexArray.UploadIfNeeded(deviceCommandContext); m_IndexArray.UploadIfNeeded(deviceCommandContext); - u8* base = m_VertexArray.Bind(deviceCommandContext); - const GLsizei stride = (GLsizei)m_VertexArray.GetStride(); - shader->VertexPointer( - m_AttributePos.format, stride, base + m_AttributePos.offset); - shader->ColorPointer( - m_AttributeColor.format, stride, base + m_AttributeColor.offset); + const uint32_t stride = m_VertexArray.GetStride(); + const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride; + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + m_AttributePos.format, firstVertexOffset + m_AttributePos.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::COLOR, + m_AttributeColor.format, firstVertexOffset + m_AttributeColor.offset, stride, 0); + + deviceCommandContext->SetVertexBuffer(0, m_VertexArray.GetBuffer()); deviceCommandContext->SetIndexBuffer(m_IndexArray.GetBuffer()); + deviceCommandContext->DrawIndexed(m_IndexArray.GetOffset(), m_EntitiesDrawn * 6, 0); g_Renderer.GetStats().m_DrawCalls++; - CVertexBuffer::Unbind(deviceCommandContext); deviceCommandContext->SetScissors(0, nullptr); } Index: ps/trunk/source/graphics/ParticleEmitter.cpp =================================================================== --- ps/trunk/source/graphics/ParticleEmitter.cpp +++ ps/trunk/source/graphics/ParticleEmitter.cpp @@ -194,30 +194,33 @@ void CParticleEmitter::RenderArray( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader)) { if (m_Particles.empty()) return; + m_VertexArray.UploadIfNeeded(deviceCommandContext); m_IndexArray.UploadIfNeeded(deviceCommandContext); - u8* base = m_VertexArray.Bind(deviceCommandContext); - - GLsizei stride = (GLsizei)m_VertexArray.GetStride(); - shader->VertexPointer( - m_AttributePos.format, stride, base + m_AttributePos.offset); + const uint32_t stride = m_VertexArray.GetStride(); + const uint32_t firstVertexOffset = m_VertexArray.GetStride() * stride; - // Pass the sin/cos axis components as texcoords for no particular reason - // other than that they fit. (Maybe this should be glVertexAttrib* instead?) - shader->TexCoordPointer( - GL_TEXTURE0, m_AttributeUV.format, stride, base + m_AttributeUV.offset); - shader->TexCoordPointer( - GL_TEXTURE1, m_AttributeAxis.format, stride, base + m_AttributeAxis.offset); - - shader->ColorPointer( - m_AttributeColor.format, stride, base + m_AttributeColor.offset); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + m_AttributePos.format, firstVertexOffset + m_AttributePos.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::COLOR, + m_AttributeColor.format, firstVertexOffset + m_AttributeColor.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + m_AttributeUV.format, firstVertexOffset + m_AttributeUV.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + m_AttributeAxis.format, firstVertexOffset + m_AttributeAxis.offset, stride, 0); + deviceCommandContext->SetVertexBuffer(0, m_VertexArray.GetBuffer()); deviceCommandContext->SetIndexBuffer(m_IndexArray.GetBuffer()); + deviceCommandContext->DrawIndexed(m_IndexArray.GetOffset(), m_Particles.size() * 6, 0); g_Renderer.GetStats().m_DrawCalls++; Index: ps/trunk/source/graphics/ShaderProgram.h =================================================================== --- ps/trunk/source/graphics/ShaderProgram.h +++ ps/trunk/source/graphics/ShaderProgram.h @@ -44,6 +44,8 @@ Renderer::Backend::GL::CShaderProgram* GetBackendShaderProgram() { return m_BackendShaderProgram.get(); } + // TODO: add reloadable handles. + protected: CShaderProgram(const CStr& name, const CShaderDefines& defines); Index: ps/trunk/source/graphics/TextRenderer.cpp =================================================================== --- ps/trunk/source/graphics/TextRenderer.cpp +++ ps/trunk/source/graphics/TextRenderer.cpp @@ -263,15 +263,23 @@ size_t idx = 0; - auto flush = [deviceCommandContext, &idx, &vertexes, &indexes, &shader]() -> void { + auto flush = [deviceCommandContext, &idx, &vertexes, &indexes]() -> void + { if (idx == 0) return; - shader->VertexPointer( - Renderer::Backend::Format::R16G16_SINT, sizeof(t2f_v2i), &vertexes[0].x); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, sizeof(t2f_v2i), &vertexes[0].u); + const uint32_t stride = sizeof(t2f_v2i); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R16G16_SINT, offsetof(t2f_v2i, x), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, offsetof(t2f_v2i, u), stride, 0); + + deviceCommandContext->SetVertexBufferData(0, vertexes.data()); deviceCommandContext->SetIndexBufferData(indexes.data()); + deviceCommandContext->DrawIndexed(0, idx * 6, 0); idx = 0; }; Index: ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp +++ ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp @@ -97,7 +97,7 @@ void DrawTexture( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, float angle, float x, float y, float x2, float y2, float mapScale) + 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 @@ -105,7 +105,8 @@ const float c = cos(angle) * mapScale; const float m = 0.5f; - float quadTex[] = { + float quadTex[] = + { m*(-c + s + 1.f), m*(-c + -s + 1.f), m*(c + s + 1.f), m*(-c + s + 1.f), m*(c + -s + 1.f), m*(c + s + 1.f), @@ -114,7 +115,8 @@ m*(-c + -s + 1.f), m*(c + -s + 1.f), m*(-c + s + 1.f), m*(-c + -s + 1.f) }; - float quadVerts[] = { + float quadVerts[] = + { x, y, 0.0f, x2, y, 0.0f, x2, y2, 0.0f, @@ -124,10 +126,15 @@ x, y, 0.0f }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, quadVerts); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); deviceCommandContext->Draw(0, 6); } @@ -440,7 +447,7 @@ 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(deviceCommandContext, shader, angle, x, y, x2, y2, m_MapScale); + DrawTexture(deviceCommandContext, angle, x, y, x2, y2, m_MapScale); deviceCommandContext->EndPass(); } Index: ps/trunk/source/ps/Profiler2GPU.h =================================================================== --- ps/trunk/source/ps/Profiler2GPU.h +++ ps/trunk/source/ps/Profiler2GPU.h @@ -42,7 +42,9 @@ void RegionLeave(const char* id); private: +#if !CONFIG2_GLES CProfiler2& m_Profiler; +#endif std::unique_ptr m_ProfilerARB; }; Index: ps/trunk/source/ps/Profiler2GPU.cpp =================================================================== --- ps/trunk/source/ps/Profiler2GPU.cpp +++ ps/trunk/source/ps/Profiler2GPU.cpp @@ -291,8 +291,7 @@ public: }; -CProfiler2GPU::CProfiler2GPU(CProfiler2& profiler) : - m_Profiler(profiler) +CProfiler2GPU::CProfiler2GPU(CProfiler2& UNUSED(profiler)) { } Index: ps/trunk/source/renderer/DebugRenderer.cpp =================================================================== --- ps/trunk/source/renderer/DebugRenderer.cpp +++ ps/trunk/source/renderer/DebugRenderer.cpp @@ -126,8 +126,11 @@ #undef ADD - debugLineShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, vertices.data()); + deviceCommandContext->Draw(0, vertices.size() / 3); deviceCommandContext->EndPass(); @@ -177,8 +180,11 @@ #undef ADD - debugCircleShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, vertices.data()); + deviceCommandContext->Draw(0, vertices.size() / 3); deviceCommandContext->EndPass(); @@ -253,8 +259,11 @@ ADD(intermediatePoints[3]); } - overlayShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, vertices.data()); + deviceCommandContext->Draw(0, vertices.size() / 3); vertices.clear(); @@ -271,8 +280,11 @@ ADD(farPoints[nextI]); } - overlayShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, vertices.data()); + deviceCommandContext->Draw(0, vertices.size() / 3); #undef ADD @@ -325,10 +337,12 @@ #undef ADD_FACE - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 3 * sizeof(float), data.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, data.data()); - deviceCommandContext->Draw(0, 6*6); + deviceCommandContext->Draw(0, 6 * 6); deviceCommandContext->EndPass(); } @@ -371,8 +385,10 @@ #undef ADD_VERT - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 3 * sizeof(float), data.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexBufferData(0, data.data()); deviceCommandContext->Draw(0, data.size() / 5); Index: ps/trunk/source/renderer/DecalRData.cpp =================================================================== --- ps/trunk/source/renderer/DecalRData.cpp +++ ps/trunk/source/renderer/DecalRData.cpp @@ -215,15 +215,25 @@ if (lastVB != batch.vertices->m_Owner) { lastVB = batch.vertices->m_Owner; - const GLsizei stride = sizeof(SDecalVertex); - SDecalVertex* base = (SDecalVertex*)batch.vertices->m_Owner->Bind(deviceCommandContext); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position[0]); - shader->NormalPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Normal[0]); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, stride, &base->m_UV[0]); + batch.vertices->m_Owner->UploadIfNeeded(deviceCommandContext); + + const uint32_t stride = sizeof(SDecalVertex); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SDecalVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SDecalVertex, m_Normal), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, + offsetof(SDecalVertex, m_UV), stride, 0); + + deviceCommandContext->SetVertexBuffer(0, batch.vertices->m_Owner->GetBuffer()); } if (lastIB != batch.indices->m_Owner) @@ -243,8 +253,6 @@ deviceCommandContext->EndPass(); } } - - CVertexBuffer::Unbind(deviceCommandContext); } void CDecalRData::BuildVertexData() Index: ps/trunk/source/renderer/HWLightingModelRenderer.h =================================================================== --- ps/trunk/source/renderer/HWLightingModelRenderer.h +++ ps/trunk/source/renderer/HWLightingModelRenderer.h @@ -39,15 +39,15 @@ CModelRData* CreateModelData(const void* key, CModel* model) override; void UpdateModelData(CModel* model, CModelRData* data, int updateflags) override; - void BeginPass(int streamflags) override; + void BeginPass() override; void EndPass( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int streamflags) override; + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) override; void PrepareModelDef( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def) override; + Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def) override; void RenderModel( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, CModel* model, CModelRData* data) override; + Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data) override; protected: struct ShaderModelRendererInternals; Index: ps/trunk/source/renderer/HWLightingModelRenderer.cpp =================================================================== --- ps/trunk/source/renderer/HWLightingModelRenderer.cpp +++ ps/trunk/source/renderer/HWLightingModelRenderer.cpp @@ -174,74 +174,70 @@ // Setup one rendering pass -void ShaderModelVertexRenderer::BeginPass(int streamflags) +void ShaderModelVertexRenderer::BeginPass() { - ENSURE(streamflags == (streamflags & (STREAM_POS | STREAM_UV0 | STREAM_UV1 | STREAM_NORMAL))); } // Cleanup one rendering pass void ShaderModelVertexRenderer::EndPass( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int UNUSED(streamflags)) + Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) { - CVertexBuffer::Unbind(deviceCommandContext); } - // Prepare UV coordinates for this modeldef void ShaderModelVertexRenderer::PrepareModelDef( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const CModelDef& def) { m->shadermodeldef = (ShaderModelDef*)def.GetRenderData(m); ENSURE(m->shadermodeldef); - u8* base = m->shadermodeldef->m_Array.Bind(deviceCommandContext); - GLsizei stride = (GLsizei)m->shadermodeldef->m_Array.GetStride(); + m->shadermodeldef->m_Array.UploadIfNeeded(deviceCommandContext); - if (streamflags & STREAM_UV0) - { - shader->TexCoordPointer( - GL_TEXTURE0, m->shadermodeldef->m_UVs[0].format, stride, - base + m->shadermodeldef->m_UVs[0].offset); - } + const uint32_t stride = m->shadermodeldef->m_Array.GetStride(); + const uint32_t firstVertexOffset = m->shadermodeldef->m_Array.GetOffset() * stride; - if ((streamflags & STREAM_UV1) && def.GetNumUVsPerVertex() >= 2) + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + m->shadermodeldef->m_UVs[0].format, + firstVertexOffset + m->shadermodeldef->m_UVs[0].offset, stride, 0); + if (def.GetNumUVsPerVertex() >= 2) { - shader->TexCoordPointer( - GL_TEXTURE1, m->shadermodeldef->m_UVs[1].format, stride, - base + m->shadermodeldef->m_UVs[1].offset); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + m->shadermodeldef->m_UVs[1].format, + firstVertexOffset + m->shadermodeldef->m_UVs[1].offset, stride, 0); } -} + deviceCommandContext->SetVertexBuffer(0, m->shadermodeldef->m_Array.GetBuffer()); +} // Render one model void ShaderModelVertexRenderer::RenderModel( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, CModel* model, CModelRData* data) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader), CModel* model, CModelRData* data) { const CModelDefPtr& mdldef = model->GetModelDef(); ShaderModel* shadermodel = static_cast(data); - u8* base = shadermodel->m_Array.Bind(deviceCommandContext); - GLsizei stride = (GLsizei)shadermodel->m_Array.GetStride(); - + shadermodel->m_Array.UploadIfNeeded(deviceCommandContext); m->shadermodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext); - deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer()); - if (streamflags & STREAM_POS) - { - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, - base + shadermodel->m_Position.offset); - } + const uint32_t stride = shadermodel->m_Array.GetStride(); + const uint32_t firstVertexOffset = shadermodel->m_Array.GetOffset() * stride; - if (streamflags & STREAM_NORMAL) - { - shader->NormalPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, - base + shadermodel->m_Normal.offset); - } + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + shadermodel->m_Position.offset, stride, 1); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + shadermodel->m_Normal.offset, stride, 1); + + deviceCommandContext->SetVertexBuffer(1, shadermodel->m_Array.GetBuffer()); + deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer()); // Render the lot. const size_t numberOfFaces = mdldef->GetNumFaces(); Index: ps/trunk/source/renderer/InstancingModelRenderer.h =================================================================== --- ps/trunk/source/renderer/InstancingModelRenderer.h +++ ps/trunk/source/renderer/InstancingModelRenderer.h @@ -42,15 +42,14 @@ CModelRData* CreateModelData(const void* key, CModel* model); void UpdateModelData(CModel* model, CModelRData* data, int updateflags); - void BeginPass(int streamflags); + void BeginPass(); void EndPass( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - int streamflags); + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); void PrepareModelDef( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def); + Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def); void RenderModel(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, CModel* model, CModelRData* data); + Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data); protected: InstancingModelRendererInternals* m; Index: ps/trunk/source/renderer/InstancingModelRenderer.cpp =================================================================== --- ps/trunk/source/renderer/InstancingModelRenderer.cpp +++ ps/trunk/source/renderer/InstancingModelRenderer.cpp @@ -295,86 +295,81 @@ // Setup one rendering pass. -void InstancingModelRenderer::BeginPass(int streamflags) +void InstancingModelRenderer::BeginPass() { - ENSURE(streamflags == (streamflags & (STREAM_POS|STREAM_NORMAL|STREAM_UV0|STREAM_UV1|STREAM_UV2|STREAM_UV3|STREAM_UV4))); } // Cleanup rendering pass. void InstancingModelRenderer::EndPass( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - int UNUSED(streamflags)) + Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) { - CVertexBuffer::Unbind(deviceCommandContext); } - // Prepare UV coordinates for this modeldef void InstancingModelRenderer::PrepareModelDef( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const CModelDef& def) { m->imodeldef = (IModelDef*)def.GetRenderData(m); ENSURE(m->imodeldef); - - u8* base = m->imodeldef->m_Array.Bind(deviceCommandContext); - GLsizei stride = (GLsizei)m->imodeldef->m_Array.GetStride(); - + m->imodeldef->m_Array.UploadIfNeeded(deviceCommandContext); m->imodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext); + deviceCommandContext->SetIndexBuffer(m->imodeldef->m_IndexArray.GetBuffer()); - if (streamflags & STREAM_POS) + const uint32_t stride = m->imodeldef->m_Array.GetStride(); + const uint32_t firstVertexOffset = m->imodeldef->m_Array.GetOffset() * stride; + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + m->imodeldef->m_Position.format, + firstVertexOffset + m->imodeldef->m_Position.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + m->imodeldef->m_Normal.format, + firstVertexOffset + m->imodeldef->m_Normal.offset, stride, 0); + + constexpr size_t MAX_UV = 2; + for (size_t uv = 0; uv < std::min(MAX_UV, def.GetNumUVsPerVertex()); ++uv) { - shader->VertexPointer( - m->imodeldef->m_Position.format, stride, - base + m->imodeldef->m_Position.offset); + const Renderer::Backend::VertexAttributeStream stream = + static_cast( + static_cast(Renderer::Backend::VertexAttributeStream::UV0) + uv); + deviceCommandContext->SetVertexAttributeFormat( + stream, m->imodeldef->m_UVs[uv].format, + firstVertexOffset + m->imodeldef->m_UVs[uv].offset, stride, 0); } - if (streamflags & STREAM_NORMAL) + // GPU skinning requires extra attributes to compute positions/normals. + if (m->gpuSkinning) { - shader->NormalPointer( - m->imodeldef->m_Normal.format, stride, - base + m->imodeldef->m_Normal.offset); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV2, + m->imodeldef->m_BlendJoints.format, + firstVertexOffset + m->imodeldef->m_BlendJoints.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV3, + m->imodeldef->m_BlendWeights.format, + firstVertexOffset + m->imodeldef->m_BlendWeights.offset, stride, 0); } if (m->calculateTangents) { - shader->VertexAttribPointer( - str_a_tangent, m->imodeldef->m_Tangent.format, - GL_FALSE, stride, base + m->imodeldef->m_Tangent.offset); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV4, + m->imodeldef->m_Tangent.format, + firstVertexOffset + m->imodeldef->m_Tangent.offset, stride, 0); } - for (size_t uv = 0; uv < 2; ++uv) - if (streamflags & (STREAM_UV0 << uv)) - { - if (def.GetNumUVsPerVertex() >= uv + 1) - { - shader->TexCoordPointer( - GL_TEXTURE0 + uv, m->imodeldef->m_UVs[uv].format, stride, - base + m->imodeldef->m_UVs[uv].offset); - } - else - ONCE(LOGERROR("Model '%s' has no UV%d set.", def.GetName().string8().c_str(), uv)); - } - - // GPU skinning requires extra attributes to compute positions/normals - if (m->gpuSkinning) - { - shader->VertexAttribPointer( - str_a_skinJoints, m->imodeldef->m_BlendJoints.format, GL_FALSE, - stride, base + m->imodeldef->m_BlendJoints.offset); - shader->VertexAttribPointer( - str_a_skinWeights, m->imodeldef->m_BlendWeights.format, GL_TRUE, - stride, base + m->imodeldef->m_BlendWeights.offset); - } + deviceCommandContext->SetVertexBuffer(0, m->imodeldef->m_Array.GetBuffer()); } // Render one model void InstancingModelRenderer::RenderModel( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int UNUSED(streamflags), CModel* model, CModelRData* UNUSED(data)) + Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* UNUSED(data)) { const CModelDefPtr& mdldef = model->GetModelDef(); @@ -398,5 +393,4 @@ // Bump stats. g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_ModelTris += numberOfFaces; - } Index: ps/trunk/source/renderer/ModelRenderer.cpp =================================================================== --- ps/trunk/source/renderer/ModelRenderer.cpp +++ ps/trunk/source/renderer/ModelRenderer.cpp @@ -608,7 +608,6 @@ deviceCommandContext->BeginPass(); Renderer::Backend::GL::CShaderProgram* shader = currentTech->GetShader(pass); - int streamflags = shader->GetStreamFlags(); modifier->BeginPass(shader); @@ -617,7 +616,7 @@ bool boundWaterTexture = false; bool boundSkyCube = false; - m->vertexRenderer->BeginPass(streamflags); + m->vertexRenderer->BeginPass(); // When the shader technique changes, textures need to be // rebound, so ensure there are no remnants from the last pass. @@ -685,7 +684,7 @@ if (newModeldef != currentModeldef) { currentModeldef = newModeldef; - m->vertexRenderer->PrepareModelDef(deviceCommandContext, shader, streamflags, *currentModeldef); + m->vertexRenderer->PrepareModelDef(deviceCommandContext, shader, *currentModeldef); } // Bind all uniforms when any change @@ -741,11 +740,11 @@ CModelRData* rdata = static_cast(model->GetRenderData()); ENSURE(rdata->GetKey() == m->vertexRenderer.get()); - m->vertexRenderer->RenderModel(deviceCommandContext, shader, streamflags, model, rdata); + m->vertexRenderer->RenderModel(deviceCommandContext, shader, model, rdata); } } - m->vertexRenderer->EndPass(deviceCommandContext, streamflags); + m->vertexRenderer->EndPass(deviceCommandContext); deviceCommandContext->EndPass(); } Index: ps/trunk/source/renderer/ModelVertexRenderer.h =================================================================== --- ps/trunk/source/renderer/ModelVertexRenderer.h +++ ps/trunk/source/renderer/ModelVertexRenderer.h @@ -88,22 +88,20 @@ /** - * BeginPass: Setup global OpenGL state for this ModelVertexRenderer. + * BeginPass: Setup backend state for this ModelVertexRenderer. * - * ModelVertexRenderer implementations should prepare "heavy" OpenGL + * ModelVertexRenderer implementations should prepare "heavy" * state such as vertex shader state to prepare for rendering models * and delivering vertex data to the fragment stage as described by - * streamflags. + * shader. * * ModelRenderer implementations must call this function before any * calls to other rendering related functions. * * Recursive calls to BeginPass are not allowed, and every BeginPass * is matched by a corresponding call to EndPass. - * - * @param streamflags Vertex streams required by the fragment stage. */ - virtual void BeginPass(int streamflags) = 0; + virtual void BeginPass() = 0; /** @@ -111,12 +109,8 @@ * * ModelRenderer implementations must call this function after * rendering related functions for one pass have been called. - * - * @param streamflags Vertex streams required by the fragment stage. - * This equals the streamflags parameter passed on the last call to - * BeginPass. */ - virtual void EndPass(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int streamflags) = 0; + virtual void EndPass(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) = 0; /** @@ -128,14 +122,11 @@ * When a ModelRenderer switches back and forth between CModelDefs, * it must call PrepareModelDef for every switch. * - * @param streamflags Vertex streams required by the fragment stage. - * This equals the streamflags parameter passed on the last call to - * BeginPass. * @param def The model definition. */ virtual void PrepareModelDef( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def) = 0; + Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def) = 0; /** @@ -147,9 +138,6 @@ * preconditions : The most recent call to PrepareModelDef since * BeginPass has been for model->GetModelDef(). * - * @param streamflags Vertex streams required by the fragment stage. - * This equals the streamflags parameter passed on the last call to - * BeginPass. * @param model The model that should be rendered. * @param data Private data for the model as returned by CreateModelData. * @@ -159,7 +147,7 @@ */ virtual void RenderModel( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, int streamflags, CModel* model, CModelRData* data) = 0; + Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data) = 0; }; Index: ps/trunk/source/renderer/OverlayRenderer.cpp =================================================================== --- ps/trunk/source/renderer/OverlayRenderer.cpp +++ ps/trunk/source/renderer/OverlayRenderer.cpp @@ -482,8 +482,6 @@ // TODO: the shaders should probably be responsible for unbinding their textures deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0); deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, 0); - - CVertexBuffer::Unbind(deviceCommandContext); } void OverlayRenderer::RenderTexturedOverlayLines( @@ -542,19 +540,16 @@ shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); - // Base offsets (in bytes) of the two backing stores relative to their owner VBO m->quadIndices.UploadIfNeeded(deviceCommandContext); - u8* vertexBase = m->quadVertices.Bind(deviceCommandContext); - GLsizei vertexStride = m->quadVertices.GetStride(); - deviceCommandContext->SetIndexBuffer(m->quadIndices.GetBuffer()); + const uint32_t vertexStride = m->quadVertices.GetStride(); + const uint32_t firstVertexOffset = m->quadVertices.GetOffset() * vertexStride; for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); ++it) { QuadBatchData& batchRenderData = it->second; const size_t batchNumQuads = batchRenderData.m_NumRenderQuads; - // Careful; some drivers don't like drawing calls with 0 stuff to draw. if (batchNumQuads == 0) continue; @@ -565,19 +560,23 @@ shader->BindTexture(str_baseTex, maskPair.m_Texture->GetBackendTexture()); shader->BindTexture(str_maskTex, maskPair.m_TextureMask->GetBackendTexture()); - int streamflags = shader->GetStreamFlags(); - - if (streamflags & STREAM_POS) - shader->VertexPointer(m->quadAttributePos.format, vertexStride, vertexBase + m->quadAttributePos.offset); - - if (streamflags & STREAM_UV0) - shader->TexCoordPointer(GL_TEXTURE0, m->quadAttributeUV.format, vertexStride, vertexBase + m->quadAttributeUV.offset); + // TODO: move setting format out of the loop, we might want move the offset + // to the index offset when it's supported. + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + m->quadAttributePos.format, firstVertexOffset + m->quadAttributePos.offset, vertexStride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::COLOR, + m->quadAttributeColor.format, firstVertexOffset + m->quadAttributeColor.offset, vertexStride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + m->quadAttributeUV.format, firstVertexOffset + m->quadAttributeUV.offset, vertexStride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + m->quadAttributeUV.format, firstVertexOffset + m->quadAttributeUV.offset, vertexStride, 0); - if (streamflags & STREAM_UV1) - shader->TexCoordPointer(GL_TEXTURE1, m->quadAttributeUV.format, vertexStride, vertexBase + m->quadAttributeUV.offset); - - if (streamflags & STREAM_COLOR) - shader->ColorPointer(m->quadAttributeColor.format, vertexStride, vertexBase + m->quadAttributeColor.offset); + deviceCommandContext->SetVertexBuffer(0, m->quadVertices.GetBuffer()); + deviceCommandContext->SetIndexBuffer(m->quadIndices.GetBuffer()); deviceCommandContext->DrawIndexed(m->quadIndices.GetOffset() + batchRenderData.m_IndicesBase, batchNumQuads * 6, 0); @@ -590,8 +589,6 @@ // TODO: the shader should probably be responsible for unbinding its textures deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0); deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, 0); - - CVertexBuffer::Unbind(deviceCommandContext); } void OverlayRenderer::RenderForegroundOverlays( @@ -638,8 +635,14 @@ {0.0f, 0.0f}, }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, sizeof(CVector2D), &uvs[0]); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(1, &uvs[0]); for (size_t i = 0; i < m->sprites.size(); ++i) { @@ -662,8 +665,7 @@ sprite->m_Position + right*sprite->m_X0 + up*sprite->m_Y1 }; - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, sizeof(CVector3D), &position[0].X); + deviceCommandContext->SetVertexBufferData(0, &position[0].X); deviceCommandContext->Draw(0, 6); @@ -767,10 +769,16 @@ shader = tech->GetShader(); + shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); + m->GenerateSphere(); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, &m->sphereVertexes[0]); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + + deviceCommandContext->SetVertexBufferData(0, m->sphereVertexes.data()); + deviceCommandContext->SetIndexBufferData(m->sphereIndexes.data()); for (size_t i = 0; i < m->spheres.size(); ++i) { @@ -781,12 +789,10 @@ transform.Scale(sphere->m_Radius, sphere->m_Radius, sphere->m_Radius); transform.Translate(sphere->m_Center); - shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); shader->Uniform(str_instancingTransform, transform); shader->Uniform(str_color, sphere->m_Color); - deviceCommandContext->SetIndexBufferData(m->sphereIndexes.data()); deviceCommandContext->DrawIndexed(0, m->sphereIndexes.size(), 0); g_Renderer.GetStats().m_DrawCalls++; Index: ps/trunk/source/renderer/ParticleRenderer.cpp =================================================================== --- ps/trunk/source/renderer/ParticleRenderer.cpp +++ ps/trunk/source/renderer/ParticleRenderer.cpp @@ -167,8 +167,6 @@ if (lastTech) deviceCommandContext->EndPass(); - - CVertexBuffer::Unbind(deviceCommandContext); } void ParticleRenderer::RenderBounds(int cullGroup) Index: ps/trunk/source/renderer/PatchRData.cpp =================================================================== --- ps/trunk/source/renderer/PatchRData.cpp +++ ps/trunk/source/renderer/PatchRData.cpp @@ -801,14 +801,24 @@ for (VertexBufferBatches::iterator itv = itt->second.begin(); itv != itt->second.end(); ++itv) { - GLsizei stride = sizeof(SBaseVertex); - SBaseVertex *base = (SBaseVertex *)itv->first->Bind(deviceCommandContext); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position[0]); - shader->NormalPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Normal[0]); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position[0]); + itv->first->UploadIfNeeded(deviceCommandContext); + + const uint32_t stride = sizeof(SBaseVertex); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBaseVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBaseVertex, m_Normal), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBaseVertex, m_Position), stride, 0); + + deviceCommandContext->SetVertexBuffer(0, itv->first->GetBuffer()); for (IndexBufferBatches::iterator it = itv->second.begin(); it != itv->second.end(); ++it) { @@ -828,8 +838,6 @@ deviceCommandContext->EndPass(); } } - - CVertexBuffer::Unbind(deviceCommandContext); } /** @@ -1027,17 +1035,29 @@ { lastVB = itv->first; previousShader = shader; - GLsizei stride = sizeof(SBlendVertex); - SBlendVertex *base = (SBlendVertex *)itv->first->Bind(deviceCommandContext); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position[0]); - shader->NormalPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Normal[0]); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position[0]); - shader->TexCoordPointer( - GL_TEXTURE1, Renderer::Backend::Format::R32G32_SFLOAT, stride, &base->m_AlphaUVs[0]); + itv->first->UploadIfNeeded(deviceCommandContext); + + const uint32_t stride = sizeof(SBlendVertex); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBlendVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBlendVertex, m_Normal), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBlendVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + Renderer::Backend::Format::R32G32_SFLOAT, + offsetof(SBlendVertex, m_AlphaUVs), stride, 0); + + deviceCommandContext->SetVertexBuffer(0, itv->first->GetBuffer()); } for (IndexBufferBatches::iterator it = itv->second.begin(); it != itv->second.end(); ++it) @@ -1059,13 +1079,11 @@ deviceCommandContext->EndPass(); } } - - CVertexBuffer::Unbind(deviceCommandContext); } void CPatchRData::RenderStreams( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const std::vector& patches, Renderer::Backend::GL::CShaderProgram* shader, + const std::vector& patches, Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const bool bindPositionAsTexCoord) { PROFILE3("render terrain streams"); @@ -1095,19 +1113,26 @@ PROFILE_END("compute batches"); + const uint32_t stride = sizeof(SBaseVertex); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBaseVertex, m_Position), stride, 0); + if (bindPositionAsTexCoord) + { + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SBaseVertex, m_Position), stride, 0); + } + // Render each batch for (const std::pair& streamBatch : batches) { - GLsizei stride = sizeof(SBaseVertex); - SBaseVertex *base = (SBaseVertex *)streamBatch.first->Bind(deviceCommandContext); + streamBatch.first->UploadIfNeeded(deviceCommandContext); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position); - if (bindPositionAsTexCoord) - { - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position); - } + deviceCommandContext->SetVertexBuffer(0, streamBatch.first->GetBuffer()); for (const std::pair& batchIndexBuffer : streamBatch.second) { @@ -1123,8 +1148,6 @@ g_Renderer.m_Stats.m_TerrainTris += std::accumulate(batch.first.begin(), batch.first.end(), 0) / 3; } } - - CVertexBuffer::Unbind(deviceCommandContext); } void CPatchRData::RenderOutline() @@ -1161,11 +1184,20 @@ void CPatchRData::RenderSides( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const std::vector& patches, Renderer::Backend::GL::CShaderProgram* shader) + const std::vector& patches, Renderer::Backend::GL::CShaderProgram* UNUSED(shader)) { PROFILE3("render terrain sides"); GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain sides"); + if (patches.empty()) + return; + + const uint32_t stride = sizeof(SSideVertex); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(SSideVertex, m_Position), stride, 0); + CVertexBuffer* lastVB = nullptr; for (CPatchRData* patch : patches) { @@ -1175,12 +1207,9 @@ if (lastVB != patch->m_VBSides->m_Owner) { lastVB = patch->m_VBSides->m_Owner; - SSideVertex *base = (SSideVertex*)patch->m_VBSides->m_Owner->Bind(deviceCommandContext); + patch->m_VBSides->m_Owner->UploadIfNeeded(deviceCommandContext); - // setup data pointers - GLsizei stride = sizeof(SSideVertex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base->m_Position); + deviceCommandContext->SetVertexBuffer(0, patch->m_VBSides->m_Owner->GetBuffer()); } deviceCommandContext->Draw(patch->m_VBSides->m_Index, (GLsizei)patch->m_VBSides->m_Count); @@ -1189,8 +1218,6 @@ g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_TerrainTris += patch->m_VBSides->m_Count / 3; } - - CVertexBuffer::Unbind(deviceCommandContext); } void CPatchRData::RenderPriorities(CTextRenderer& textRenderer) @@ -1422,63 +1449,69 @@ void CPatchRData::RenderWaterSurface( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader, const bool bindWaterData) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const bool bindWaterData) { ASSERT(m_UpdateFlags == 0); if (!m_VBWater) return; + m_VBWater->m_Owner->UploadIfNeeded(deviceCommandContext); m_VBWaterIndices->m_Owner->UploadIfNeeded(deviceCommandContext); - SWaterVertex* base = reinterpret_cast(m_VBWater->m_Owner->Bind(deviceCommandContext)); + const uint32_t stride = sizeof(SWaterVertex); + const uint32_t firstVertexOffset = m_VBWater->m_Index * stride; - // Setup data pointers. - const GLsizei stride = sizeof(SWaterVertex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base[m_VBWater->m_Index].m_Position); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWaterVertex, m_Position), stride, 0); if (bindWaterData) { - shader->VertexAttribPointer( - str_a_waterInfo, Renderer::Backend::Format::R32G32_SFLOAT, false, stride, - &base[m_VBWater->m_Index].m_WaterData); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + Renderer::Backend::Format::R32G32_SFLOAT, + firstVertexOffset + offsetof(SWaterVertex, m_WaterData), stride, 0); } + deviceCommandContext->SetVertexBuffer(0, m_VBWater->m_Owner->GetBuffer()); 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; - - CVertexBuffer::Unbind(deviceCommandContext); } void CPatchRData::RenderWaterShore( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - Renderer::Backend::GL::CShaderProgram* shader) + Renderer::Backend::GL::CShaderProgram* UNUSED(shader)) { ASSERT(m_UpdateFlags == 0); if (!m_VBWaterShore) return; + m_VBWaterShore->m_Owner->UploadIfNeeded(deviceCommandContext); m_VBWaterIndicesShore->m_Owner->UploadIfNeeded(deviceCommandContext); - SWaterVertex* base = reinterpret_cast(m_VBWaterShore->m_Owner->Bind(deviceCommandContext)); + const uint32_t stride = sizeof(SWaterVertex); + const uint32_t firstVertexOffset = m_VBWaterShore->m_Index * stride; - const GLsizei stride = sizeof(SWaterVertex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, - &base[m_VBWaterShore->m_Index].m_Position); - shader->VertexAttribPointer( - str_a_waterInfo, Renderer::Backend::Format::R32G32_SFLOAT, false, stride, - &base[m_VBWaterShore->m_Index].m_WaterData); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWaterVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + Renderer::Backend::Format::R32G32_SFLOAT, + firstVertexOffset + offsetof(SWaterVertex, m_WaterData), stride, 0); + deviceCommandContext->SetVertexBuffer(0, m_VBWaterShore->m_Owner->GetBuffer()); 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; - - CVertexBuffer::Unbind(deviceCommandContext); } Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -208,6 +208,7 @@ const SViewPort vp = { 0, 0, inWidth / 2, inHeight / 2 }; g_Renderer.SetViewport(vp); + // TODO: remove the fullscreen quad drawing duplication. float quadVerts[] = { 1.0f, 1.0f, @@ -228,10 +229,17 @@ 1.0f, 0.0f, 1.0f, 1.0f }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, quadVerts); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); + deviceCommandContext->Draw(0, 6); g_Renderer.SetViewport(oldVp); @@ -285,10 +293,17 @@ 1.0f, 0.0f, 1.0f, 1.0f }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, quadVerts); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); + deviceCommandContext->Draw(0, 6); g_Renderer.SetViewport(oldVp); @@ -313,10 +328,16 @@ g_Renderer.SetViewport(vp); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, quadVerts); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); + deviceCommandContext->Draw(0, 6); g_Renderer.SetViewport(oldVp); @@ -434,10 +455,17 @@ 1.0f, 0.0f, 1.0f, 1.0f }; - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, quadTex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, quadVerts); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, quadVerts); + deviceCommandContext->SetVertexBufferData(1, quadTex); + deviceCommandContext->Draw(0, 6); deviceCommandContext->EndPass(); Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -749,10 +749,16 @@ 1,0, 0,1, 1,1 }; - texShader->VertexPointer( - Renderer::Backend::Format::R32G32_SFLOAT, 0, boxVerts); - texShader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, 0, boxUV); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1); + + deviceCommandContext->SetVertexBufferData(0, boxVerts); + deviceCommandContext->SetVertexBufferData(1, boxUV); + deviceCommandContext->Draw(0, 6); deviceCommandContext->EndPass(); Index: ps/trunk/source/renderer/SilhouetteRenderer.cpp =================================================================== --- ps/trunk/source/renderer/SilhouetteRenderer.cpp +++ ps/trunk/source/renderer/SilhouetteRenderer.cpp @@ -493,8 +493,13 @@ r.x1, r.y1, r.x0, r.y1, }; - shader->VertexPointer( - Renderer::Backend::Format::R16G16_SINT, 0, verts); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R16G16_SINT, 0, 0, 0); + + deviceCommandContext->SetVertexBufferData(0, verts); + deviceCommandContext->Draw(0, 6); } Index: ps/trunk/source/renderer/SkyManager.cpp =================================================================== --- ps/trunk/source/renderer/SkyManager.cpp +++ ps/trunk/source/renderer/SkyManager.cpp @@ -246,14 +246,19 @@ camera.GetViewProjection() * translate * rotate * scale); m_VertexArray.PrepareForRendering(); + m_VertexArray.UploadIfNeeded(deviceCommandContext); - u8* base = m_VertexArray.Bind(deviceCommandContext); - const GLsizei stride = static_cast(m_VertexArray.GetStride()); + const uint32_t stride = m_VertexArray.GetStride(); + const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride; - shader->VertexPointer( - m_AttributePosition.format, stride, base + m_AttributePosition.offset); - shader->TexCoordPointer( - GL_TEXTURE0, m_AttributeUV.format, stride, base + m_AttributeUV.offset); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, m_AttributePosition.format, + firstVertexOffset + m_AttributePosition.offset, stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, m_AttributeUV.format, + firstVertexOffset + m_AttributeUV.offset, stride, 0); + + deviceCommandContext->SetVertexBuffer(0, m_VertexArray.GetBuffer()); deviceCommandContext->Draw(0, m_VertexArray.GetNumberOfVertices()); Index: ps/trunk/source/renderer/TerrainOverlay.cpp =================================================================== --- ps/trunk/source/renderer/TerrainOverlay.cpp +++ ps/trunk/source/renderer/TerrainOverlay.cpp @@ -229,8 +229,11 @@ overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); overlayShader->Uniform(str_color, color); - overlayShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + + deviceCommandContext->SetVertexBufferData(0, vertices.data()); deviceCommandContext->Draw(0, vertices.size() / 3); @@ -297,8 +300,11 @@ overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); overlayShader->Uniform(str_color, color); - overlayShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, 0, vertices.data()); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + + deviceCommandContext->SetVertexBufferData(0, vertices.data()); deviceCommandContext->Draw(0, vertices.size() / 3); Index: ps/trunk/source/renderer/TerrainRenderer.cpp =================================================================== --- ps/trunk/source/renderer/TerrainRenderer.cpp +++ ps/trunk/source/renderer/TerrainRenderer.cpp @@ -207,11 +207,14 @@ waterBounds[0].X, height, waterBounds[1].Z }; - const GLsizei stride = sizeof(float) * 3; - debugOverlayShader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, waterPos); - debugOverlayShader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R32G32B32_SFLOAT, stride, waterPos); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0, 0); + + deviceCommandContext->SetVertexBufferData(0, waterPos); deviceCommandContext->Draw(0, 6); } Index: ps/trunk/source/renderer/TexturedLineRData.cpp =================================================================== --- ps/trunk/source/renderer/TexturedLineRData.cpp +++ ps/trunk/source/renderer/TexturedLineRData.cpp @@ -44,29 +44,32 @@ // -- render main line quad strip ---------------------- - const int streamFlags = shader->GetStreamFlags(); - line.m_TextureBase->UploadBackendTextureIfNeeded(deviceCommandContext); line.m_TextureMask->UploadBackendTextureIfNeeded(deviceCommandContext); + m_VB->m_Owner->UploadIfNeeded(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); - GLsizei stride = sizeof(CTexturedLineRData::SVertex); - CTexturedLineRData::SVertex* vertexBase = - reinterpret_cast(m_VB->m_Owner->Bind(deviceCommandContext)); - - if (streamFlags & STREAM_POS) - shader->VertexPointer(Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &vertexBase->m_Position[0]); + const uint32_t stride = sizeof(CTexturedLineRData::SVertex); - if (streamFlags & STREAM_UV0) - shader->TexCoordPointer(GL_TEXTURE0, Renderer::Backend::Format::R32G32_SFLOAT, stride, &vertexBase->m_UVs[0]); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + offsetof(CTexturedLineRData::SVertex, m_Position), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R32G32_SFLOAT, + offsetof(CTexturedLineRData::SVertex, m_UVs), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + Renderer::Backend::Format::R32G32_SFLOAT, + offsetof(CTexturedLineRData::SVertex, m_UVs), stride, 0); - if (streamFlags & STREAM_UV1) - shader->TexCoordPointer(GL_TEXTURE1, Renderer::Backend::Format::R32G32_SFLOAT, stride, &vertexBase->m_UVs[0]); + deviceCommandContext->SetVertexBuffer(0, m_VB->m_Owner->GetBuffer()); deviceCommandContext->SetIndexBuffer(m_VBIndices->m_Owner->GetBuffer()); deviceCommandContext->DrawIndexed(m_VBIndices->m_Index, m_VBIndices->m_Count, 0); Index: ps/trunk/source/renderer/VertexArray.h =================================================================== --- ps/trunk/source/renderer/VertexArray.h +++ ps/trunk/source/renderer/VertexArray.h @@ -181,8 +181,7 @@ 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, Index: ps/trunk/source/renderer/VertexArray.cpp =================================================================== --- ps/trunk/source/renderer/VertexArray.cpp +++ ps/trunk/source/renderer/VertexArray.cpp @@ -282,21 +282,6 @@ m_VB->m_Owner->UpdateChunkVertices(m_VB.Get(), m_BackingStore); } - -// Bind this array, returns the base address for calls to glVertexPointer etc. -u8* VertexArray::Bind( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) -{ - if (!m_VB) - return nullptr; - - 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) { Index: ps/trunk/source/renderer/VertexBuffer.h =================================================================== --- ps/trunk/source/renderer/VertexBuffer.h +++ ps/trunk/source/renderer/VertexBuffer.h @@ -34,23 +34,23 @@ * * The class can be used in two modes, depending on the usage parameter: * - * GL_STATIC_DRAW: Call Allocate() with backingStore = NULL. Then call + * Static buffer: Call Allocate() with backingStore = nullptr. Then call * UpdateChunkVertices() with any pointer - the data will be immediately copied * to the VBO. This should be used for vertex data that rarely changes. * - * GL_DYNAMIC_DRAW, GL_STREAM_DRAW: Call Allocate() with backingStore pointing + * Dynamic buffer: Call Allocate() with backingStore pointing * at some memory that will remain valid for the lifetime of the CVertexBuffer. * This should be used for vertex data that may change every frame. * Rendering is expected to occur in two phases: * - "Prepare" phase: - * If this chunk is going to be used for rendering during the next Bind phase, + * If this chunk is going to be used for rendering during the next rendering phase, * you must call PrepareForRendering(). - * If the vertex data in backingStore has been modified since the last Bind phase, + * If the vertex data in backingStore has been modified since the last uploading phase, * you must call UpdateChunkVertices(). - * - "Bind" phase: - * Bind() can be called (multiple times). The vertex data will be uploaded + * - "Upload" phase: + * UploadedIfNeeded() can be called (multiple times). The vertex data will be uploaded * to the GPU if necessary. - * It is okay to have multiple prepare/bind cycles per frame (though slightly less + * It is okay to have multiple prepare/upload cycles per frame (though slightly less * efficient), but they must occur sequentially. */ class CVertexBuffer @@ -76,7 +76,7 @@ bool m_Dirty; /// If true, we have been told this chunk is going to be used for - /// rendering in the next bind phase and will need to be uploaded + /// rendering in the next uploading phase and will need to be uploaded bool m_Needed; private: @@ -98,17 +98,9 @@ const size_t maximumBufferSize); ~CVertexBuffer(); - /// Bind to this buffer; return pointer to address required as parameter - /// 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); - - /// Make the vertex data available for the next call to Bind() + /// Make the vertex data available for the next usage. void PrepareForRendering(VBChunk* chunk); /// Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer. Index: ps/trunk/source/renderer/VertexBuffer.cpp =================================================================== --- ps/trunk/source/renderer/VertexBuffer.cpp +++ ps/trunk/source/renderer/VertexBuffer.cpp @@ -290,25 +290,6 @@ } } -// 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; -} - -void CVertexBuffer::Unbind( - Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) -{ - deviceCommandContext->BindBuffer( - Renderer::Backend::GL::CBuffer::Type::VERTEX, nullptr); - deviceCommandContext->BindBuffer( - Renderer::Backend::GL::CBuffer::Type::INDEX, nullptr); -} - size_t CVertexBuffer::GetBytesReserved() const { return MAX_VB_SIZE_BYTES; Index: ps/trunk/source/renderer/WaterManager.cpp =================================================================== --- ps/trunk/source/renderer/WaterManager.cpp +++ ps/trunk/source/renderer/WaterManager.cpp @@ -823,28 +823,44 @@ continue; CVertexBuffer::VBChunk* VBchunk = m_ShoreWaves[a]->m_VBVertices.Get(); - SWavesVertex* base = (SWavesVertex*)VBchunk->m_Owner->Bind(deviceCommandContext); + VBchunk->m_Owner->UploadIfNeeded(deviceCommandContext); + m_ShoreWavesVBIndices->m_Owner->UploadIfNeeded(deviceCommandContext); + + const uint32_t stride = sizeof(SWavesVertex); + const uint32_t firstVertexOffset = VBchunk->m_Index * stride; - // setup data pointers - GLsizei stride = sizeof(SWavesVertex); - shader->VertexPointer( - Renderer::Backend::Format::R32G32B32_SFLOAT, stride, &base[VBchunk->m_Index].m_BasePosition); - shader->TexCoordPointer( - GL_TEXTURE0, Renderer::Backend::Format::R8G8_UINT, stride, &base[VBchunk->m_Index].m_UV); - shader->NormalPointer( - Renderer::Backend::Format::R32G32_SFLOAT, stride, &base[VBchunk->m_Index].m_PerpVect); - shader->VertexAttribPointer( - str_a_apexPosition, Renderer::Backend::Format::R32G32B32_SFLOAT, false, stride, &base[VBchunk->m_Index].m_ApexPosition); - shader->VertexAttribPointer( - str_a_splashPosition, Renderer::Backend::Format::R32G32B32_SFLOAT, false, stride, &base[VBchunk->m_Index].m_SplashPosition); - shader->VertexAttribPointer( - str_a_retreatPosition, Renderer::Backend::Format::R32G32B32_SFLOAT, false, stride, &base[VBchunk->m_Index].m_RetreatPosition); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::POSITION, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWavesVertex, m_BasePosition), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::NORMAL, + Renderer::Backend::Format::R32G32_SFLOAT, + firstVertexOffset + offsetof(SWavesVertex, m_PerpVect), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV0, + Renderer::Backend::Format::R8G8_UINT, + firstVertexOffset + offsetof(SWavesVertex, m_UV), stride, 0); + + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV1, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWavesVertex, m_ApexPosition), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV2, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWavesVertex, m_SplashPosition), stride, 0); + deviceCommandContext->SetVertexAttributeFormat( + Renderer::Backend::VertexAttributeStream::UV3, + Renderer::Backend::Format::R32G32B32_SFLOAT, + firstVertexOffset + offsetof(SWavesVertex, m_RetreatPosition), stride, 0); shader->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff); shader->Uniform(str_width, (int)m_ShoreWaves[a]->m_Width); - m_ShoreWavesVBIndices->m_Owner->UploadIfNeeded(deviceCommandContext); + deviceCommandContext->SetVertexBuffer(0, VBchunk->m_Owner->GetBuffer()); 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); @@ -852,8 +868,6 @@ // TODO: figure out why this doesn't work. //g_Renderer.m_Stats.m_DrawCalls++; //g_Renderer.m_Stats.m_WaterTris += m_ShoreWaves_VBIndices->m_Count / 3; - - CVertexBuffer::Unbind(deviceCommandContext); } deviceCommandContext->EndPass(); deviceCommandContext->SetFramebuffer( Index: ps/trunk/source/renderer/backend/IShaderProgram.h =================================================================== --- ps/trunk/source/renderer/backend/IShaderProgram.h +++ ps/trunk/source/renderer/backend/IShaderProgram.h @@ -24,6 +24,21 @@ namespace Backend { +enum class VertexAttributeStream : uint32_t +{ + POSITION, + NORMAL, + COLOR, + UV0, + UV1, + UV2, + UV3, + UV4, + UV5, + UV6, + UV7, +}; + /** * IShaderProgram is a container for multiple shaders of different types. */ Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h @@ -88,6 +88,15 @@ void SetScissors(const uint32_t scissorCount, const Rect* scissors); void SetViewports(const uint32_t viewportCount, const Rect* viewports); + void SetVertexAttributeFormat( + const VertexAttributeStream stream, + const Format format, + const uint32_t offset, + const uint32_t stride, + const uint32_t bindingSlot); + void SetVertexBuffer(const uint32_t bindingSlot, CBuffer* buffer); + void SetVertexBufferData(const uint32_t bindingSlot, const void* data); + void SetIndexBuffer(CBuffer* buffer); void SetIndexBufferData(const void* data); @@ -107,7 +116,7 @@ // TODO: remove direct binding after moving shaders. void BindTexture(const uint32_t unit, const GLenum target, const GLuint handle); - void BindBuffer(const CBuffer::Type type, CBuffer* buffer); + // We need to know when to invalidate our texture bind cache. void OnTextureDestroy(CTexture* texture); @@ -125,6 +134,8 @@ void SetGraphicsPipelineStateImpl( const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force); + void BindBuffer(const CBuffer::Type type, CBuffer* buffer); + CDevice* m_Device = nullptr; GraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{}; @@ -135,6 +146,7 @@ uint32_t m_ScopedLabelDepth = 0; + CBuffer* m_VertexBuffer = nullptr; CBuffer* m_IndexBuffer = nullptr; const void* m_IndexBufferData = nullptr; @@ -154,6 +166,34 @@ CDeviceCommandContext* m_DeviceCommandContext = nullptr; BindUnit m_OldBindUnit; }; + + using BoundBuffer = std::pair; + std::array m_BoundBuffers; + class ScopedBufferBind + { + public: + ScopedBufferBind( + CDeviceCommandContext* deviceCommandContext, CBuffer* buffer); + + ~ScopedBufferBind(); + private: + CDeviceCommandContext* m_DeviceCommandContext = nullptr; + size_t m_CacheIndex = 0; + }; + + struct VertexAttributeFormat + { + Format format; + uint32_t offset; + uint32_t stride; + uint32_t bindingSlot; + + bool active; + bool initialized; + }; + std::array< + VertexAttributeFormat, + static_cast(VertexAttributeStream::UV7) + 1> m_VertexAttributeFormat; }; } // namespace GL Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -150,6 +150,21 @@ glBindTexture(GL_TEXTURE_2D, 0); for (std::pair& unit : m_BoundTextures) unit.first = unit.second = 0; + for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index) + { + m_VertexAttributeFormat[index].active = false; + m_VertexAttributeFormat[index].initialized = false; + m_VertexAttributeFormat[index].bindingSlot = 0; + } + + for (size_t index = 0; index < m_BoundBuffers.size(); ++index) + { + const CBuffer::Type type = static_cast(index); + const GLenum target = BufferTypeToGLTarget(type); + const GLuint handle = 0; + m_BoundBuffers[index].first = target; + m_BoundBuffers[index].second = handle; + } } CDeviceCommandContext::~CDeviceCommandContext() = default; @@ -302,7 +317,7 @@ ENSURE(data); ENSURE(dataOffset + dataSize <= buffer->GetSize()); const GLenum target = BufferTypeToGLTarget(buffer->GetType()); - glBindBufferARB(target, buffer->GetHandle()); + ScopedBufferBind scopedBufferBind(this, buffer); if (buffer->IsDynamic()) { // Tell the driver that it can reallocate the whole VBO @@ -322,7 +337,6 @@ { glBufferSubDataARB(target, dataOffset, dataSize, data); } - glBindBufferARB(target, 0); } void CDeviceCommandContext::UploadBufferRegion( @@ -331,10 +345,9 @@ { ENSURE(dataOffset + dataSize <= buffer->GetSize()); const GLenum target = BufferTypeToGLTarget(buffer->GetType()); - glBindBufferARB(target, buffer->GetHandle()); + ScopedBufferBind scopedBufferBind(this, buffer); ENSURE(buffer->IsDynamic()); UploadBufferRegionImpl(target, dataOffset, dataSize, uploadFunction); - glBindBufferARB(target, 0); } void CDeviceCommandContext::BeginScopedLabel(const char* name) @@ -381,13 +394,24 @@ void CDeviceCommandContext::BindBuffer(const CBuffer::Type type, CBuffer* buffer) { ENSURE(!buffer || buffer->GetType() == type); - if (type == CBuffer::Type::INDEX) + if (type == CBuffer::Type::VERTEX) + { + if (m_VertexBuffer == buffer) + return; + m_VertexBuffer = buffer; + } + else if (type == CBuffer::Type::INDEX) { if (!buffer) m_IndexBuffer = nullptr; m_IndexBufferData = nullptr; } - glBindBufferARB(BufferTypeToGLTarget(type), buffer ? buffer->GetHandle() : 0); + const GLenum target = BufferTypeToGLTarget(type); + const GLuint handle = buffer ? buffer->GetHandle() : 0; + glBindBufferARB(target, handle); + const size_t cacheIndex = static_cast(type); + ENSURE(cacheIndex < m_BoundBuffers.size()); + m_BoundBuffers[cacheIndex].second = handle; } void CDeviceCommandContext::OnTextureDestroy(CTexture* texture) @@ -437,6 +461,13 @@ { nextShaderProgram = static_cast(pipelineStateDesc.shaderProgram); + for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index) + { + const VertexAttributeStream stream = static_cast(index); + m_VertexAttributeFormat[index].active = nextShaderProgram->IsStreamActive(stream); + m_VertexAttributeFormat[index].initialized = false; + m_VertexAttributeFormat[index].bindingSlot = std::numeric_limits::max(); + } } if (nextShaderProgram) nextShaderProgram->Bind(currentShaderProgram); @@ -709,6 +740,7 @@ mask |= GL_STENCIL_BUFFER_BIT; } glClear(mask); + ogl_WarnIfError(); if (needsColor) ApplyColorMask(m_GraphicsPipelineStateDesc.blendState.colorWriteMask); if (needsDepth) @@ -762,6 +794,71 @@ glViewport(viewports[0].x, viewports[0].y, viewports[0].width, viewports[0].height); } +void CDeviceCommandContext::SetVertexAttributeFormat( + const VertexAttributeStream stream, + const Format format, + const uint32_t offset, + const uint32_t stride, + const uint32_t bindingSlot) +{ + const uint32_t index = static_cast(stream); + ENSURE(index < m_VertexAttributeFormat.size()); + ENSURE(bindingSlot < m_VertexAttributeFormat.size()); + if (!m_VertexAttributeFormat[index].active) + return; + m_VertexAttributeFormat[index].format = format; + m_VertexAttributeFormat[index].offset = offset; + m_VertexAttributeFormat[index].stride = stride; + m_VertexAttributeFormat[index].bindingSlot = bindingSlot; + + m_VertexAttributeFormat[index].initialized = true; +} + +void CDeviceCommandContext::SetVertexBuffer( + const uint32_t bindingSlot, CBuffer* buffer) +{ + ENSURE(buffer); + ENSURE(buffer->GetType() == CBuffer::Type::VERTEX); + ENSURE(m_GraphicsPipelineStateDesc.shaderProgram); + BindBuffer(buffer->GetType(), buffer); + CShaderProgram* shaderProgram = + static_cast(m_GraphicsPipelineStateDesc.shaderProgram); + for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index) + { + if (!m_VertexAttributeFormat[index].active || m_VertexAttributeFormat[index].bindingSlot != bindingSlot) + continue; + ENSURE(m_VertexAttributeFormat[index].initialized); + const VertexAttributeStream stream = static_cast(index); + shaderProgram->VertexAttribPointer(stream, + m_VertexAttributeFormat[index].format, + m_VertexAttributeFormat[index].offset, + m_VertexAttributeFormat[index].stride, + nullptr); + } +} + +void CDeviceCommandContext::SetVertexBufferData( + const uint32_t bindingSlot, const void* data) +{ + ENSURE(data); + ENSURE(m_GraphicsPipelineStateDesc.shaderProgram); + BindBuffer(CBuffer::Type::VERTEX, nullptr); + CShaderProgram* shaderProgram = + static_cast(m_GraphicsPipelineStateDesc.shaderProgram); + for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index) + { + if (!m_VertexAttributeFormat[index].active || m_VertexAttributeFormat[index].bindingSlot != bindingSlot) + continue; + ENSURE(m_VertexAttributeFormat[index].initialized); + const VertexAttributeStream stream = static_cast(index); + shaderProgram->VertexAttribPointer(stream, + m_VertexAttributeFormat[index].format, + m_VertexAttributeFormat[index].offset, + m_VertexAttributeFormat[index].stride, + data); + } +} + void CDeviceCommandContext::SetIndexBuffer(CBuffer* buffer) { ENSURE(buffer->GetType() == CBuffer::Type::INDEX); @@ -804,6 +901,7 @@ static_cast(m_GraphicsPipelineStateDesc.shaderProgram) ->AssertPointersBound(); glDrawArrays(GL_TRIANGLES, firstVertex, vertexCount); + ogl_WarnIfError(); } void CDeviceCommandContext::DrawIndexed( @@ -826,6 +924,7 @@ // in Mesa 7.10 swrast with index VBOs). glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, static_cast((static_cast(m_IndexBufferData) + sizeof(uint16_t) * firstIndex))); + ogl_WarnIfError(); } void CDeviceCommandContext::DrawIndexedInRange( @@ -850,6 +949,7 @@ #else glDrawRangeElementsEXT(GL_TRIANGLES, start, end, indexCount, GL_UNSIGNED_SHORT, indices); #endif + ogl_WarnIfError(); } CDeviceCommandContext::ScopedBind::ScopedBind( @@ -868,6 +968,24 @@ m_DeviceCommandContext->m_ActiveTextureUnit, m_OldBindUnit.first, m_OldBindUnit.second); } +CDeviceCommandContext::ScopedBufferBind::ScopedBufferBind( + CDeviceCommandContext* deviceCommandContext, CBuffer* buffer) + : m_DeviceCommandContext(deviceCommandContext) +{ + ENSURE(buffer); + m_CacheIndex = static_cast(buffer->GetType()); + const GLenum target = BufferTypeToGLTarget(buffer->GetType()); + const GLuint handle = buffer->GetHandle(); + glBindBufferARB(target, handle); +} + +CDeviceCommandContext::ScopedBufferBind::~ScopedBufferBind() +{ + glBindBufferARB( + m_DeviceCommandContext->m_BoundBuffers[m_CacheIndex].first, + m_DeviceCommandContext->m_BoundBuffers[m_CacheIndex].second); +} + } // namespace GL } // namespace Backend Index: ps/trunk/source/renderer/backend/gl/ShaderProgram.h =================================================================== --- ps/trunk/source/renderer/backend/gl/ShaderProgram.h +++ ps/trunk/source/renderer/backend/gl/ShaderProgram.h @@ -34,22 +34,6 @@ class CShaderDefines; class CStrIntern; -// Vertex data stream flags -enum -{ - STREAM_POS = (1 << 0), - STREAM_NORMAL = (1 << 1), - STREAM_COLOR = (1 << 2), - STREAM_UV0 = (1 << 3), - STREAM_UV1 = (1 << 4), - STREAM_UV2 = (1 << 5), - STREAM_UV3 = (1 << 6), - STREAM_UV4 = (1 << 7), - STREAM_UV5 = (1 << 8), - STREAM_UV6 = (1 << 9), - STREAM_UV7 = (1 << 10), -}; - namespace Renderer { @@ -124,12 +108,6 @@ */ virtual void Unbind() = 0; - /** - * Returns bitset of STREAM_* value, indicating what vertex data streams the - * vertex shader needs (e.g. position, color, UV, ...). - */ - int GetStreamFlags() const; - virtual Binding GetTextureBinding(texture_id_t id) = 0; @@ -165,11 +143,11 @@ // Vertex attribute pointers (equivalent to glVertexPointer etc): - virtual void VertexPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); - virtual void NormalPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); - virtual void ColorPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); - virtual void TexCoordPointer(GLenum texture, const Renderer::Backend::Format format, GLsizei stride, const void* pointer); - virtual void VertexAttribPointer(attrib_id_t id, const Renderer::Backend::Format format, GLboolean normalized, GLsizei stride, const void* pointer); + virtual void VertexAttribPointer( + const VertexAttributeStream stream, const Format format, + const uint32_t offset, const uint32_t stride, const void* data); + + bool IsStreamActive(const VertexAttributeStream stream) const; /** * Checks that all the required vertex attributes have been set. @@ -201,6 +179,12 @@ const std::map& vertexAttribs, int streamflags); + void VertexPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); + void NormalPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); + void ColorPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer); + void TexCoordPointer(GLenum texture, const Renderer::Backend::Format format, GLsizei stride, const void* pointer); + void VertexAttribPointer(attrib_id_t id, const Renderer::Backend::Format format, GLboolean normalized, GLsizei stride, const void* pointer); + virtual void BindTexture(texture_id_t id, GLuint tex) = 0; virtual void BindTexture(Binding id, GLuint tex) = 0; Index: ps/trunk/source/renderer/backend/gl/ShaderProgram.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/ShaderProgram.cpp +++ ps/trunk/source/renderer/backend/gl/ShaderProgram.cpp @@ -53,7 +53,12 @@ namespace { -GLint GLSizeFromFormat(const Renderer::Backend::Format format) +int GetStreamMask(const VertexAttributeStream stream) +{ + return 1 << static_cast(stream); +} + +GLint GLSizeFromFormat(const Format format) { GLint size = 1; if (format == Renderer::Backend::Format::R32_SFLOAT || @@ -77,7 +82,7 @@ return size; } -GLenum GLTypeFromFormat(const Renderer::Backend::Format format) +GLenum GLTypeFromFormat(const Format format) { GLenum type = GL_FLOAT; if (format == Renderer::Backend::Format::R32_SFLOAT || @@ -100,27 +105,31 @@ return type; } -int GetAttributeLocationFromStream(Renderer::Backend::GL::CDevice* device, const int stream) +GLboolean NormalizedFromFormat(const Format format) +{ + switch (format) + { + case Format::R8G8_UNORM: FALLTHROUGH; + case Format::R8G8B8_UNORM: FALLTHROUGH; + case Format::R8G8B8A8_UNORM: FALLTHROUGH; + case Format::R16_UNORM: FALLTHROUGH; + case Format::R16G16_UNORM: + return GL_TRUE; + default: + break; + } + return GL_FALSE; +} + +int GetAttributeLocationFromStream( + CDevice* device, const VertexAttributeStream stream) { // Old mapping makes sense only if we have an old/low-end hardware. Else we // need to use sequential numbering to fix #3054. We use presence of // compute shaders as a check that the hardware has universal CUs. if (device->GetCapabilities().computeShaders) { - switch (stream) - { - case STREAM_POS: return 0; - case STREAM_NORMAL: return 1; - case STREAM_COLOR: return 2; - case STREAM_UV0: return 3; - case STREAM_UV1: return 4; - case STREAM_UV2: return 5; - case STREAM_UV3: return 6; - case STREAM_UV4: return 7; - case STREAM_UV5: return 8; - case STREAM_UV6: return 9; - case STREAM_UV7: return 10; - } + return static_cast(stream); } else { @@ -129,17 +138,17 @@ // https://developer.download.nvidia.com/opengl/glsl/glsl_release_notes.pdf switch (stream) { - case STREAM_POS: return 0; - case STREAM_NORMAL: return 2; - case STREAM_COLOR: return 3; - case STREAM_UV0: return 8; - case STREAM_UV1: return 9; - case STREAM_UV2: return 10; - case STREAM_UV3: return 11; - case STREAM_UV4: return 12; - case STREAM_UV5: return 13; - case STREAM_UV6: return 14; - case STREAM_UV7: return 15; + case VertexAttributeStream::POSITION: return 0; + case VertexAttributeStream::NORMAL: return 2; + case VertexAttributeStream::COLOR: return 3; + case VertexAttributeStream::UV0: return 8; + case VertexAttributeStream::UV1: return 9; + case VertexAttributeStream::UV2: return 10; + case VertexAttributeStream::UV3: return 11; + case VertexAttributeStream::UV4: return 12; + case VertexAttributeStream::UV5: return 13; + case VertexAttributeStream::UV6: return 14; + case VertexAttributeStream::UV7: return 15; } } @@ -269,11 +278,20 @@ void Bind(CShaderProgram* previousShaderProgram) override { + CShaderProgramARB* previousShaderProgramARB = nullptr; if (previousShaderProgram) - previousShaderProgram->Unbind(); + previousShaderProgramARB = static_cast(previousShaderProgramARB); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_VertexProgram); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_FragmentProgram); + if (previousShaderProgramARB) + previousShaderProgramARB->UnbindClientStates(); + + if (!previousShaderProgramARB || + previousShaderProgramARB->m_VertexProgram != m_VertexProgram || + previousShaderProgramARB->m_FragmentProgram != m_FragmentProgram) + { + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_VertexProgram); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_FragmentProgram); + } BindClientStates(); } @@ -680,6 +698,8 @@ for (const int index : m_ActiveVertexAttributes) glEnableVertexAttribArray(index); } + + m_ValidStreams = 0; } void Unbind() override @@ -777,52 +797,21 @@ } } - // Map the various fixed-function Pointer functions onto generic vertex attributes - // (matching the attribute indexes from ShaderManager's ParseAttribSemantics): - - void VertexPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer) override - { - const GLint size = GLSizeFromFormat(format); - const GLenum type = GLTypeFromFormat(format); - glVertexAttribPointer(0, size, type, GL_FALSE, stride, pointer); - m_ValidStreams |= STREAM_POS; - } - - void NormalPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer) override - { - const GLint size = GLSizeFromFormat(format); - const GLenum type = GLTypeFromFormat(format); - glVertexAttribPointer(m_Device->GetCapabilities().computeShaders ? 1 : 2, size, type, (type == GL_FLOAT ? GL_FALSE : GL_TRUE), stride, pointer); - m_ValidStreams |= STREAM_NORMAL; - } - - void ColorPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer) override - { - const GLint size = GLSizeFromFormat(format); - const GLenum type = GLTypeFromFormat(format); - glVertexAttribPointer(m_Device->GetCapabilities().computeShaders ? 2 : 3, size, type, (type == GL_FLOAT ? GL_FALSE : GL_TRUE), stride, pointer); - m_ValidStreams |= STREAM_COLOR; - } - - void TexCoordPointer(GLenum texture, const Renderer::Backend::Format format, GLsizei stride, const void* pointer) override - { + void VertexAttribPointer( + const VertexAttributeStream stream, const Format format, + const uint32_t offset, const uint32_t stride, const void* data) override + { + const int attributeLocation = GetAttributeLocationFromStream(m_Device, stream); + std::vector::const_iterator it = + std::lower_bound(m_ActiveVertexAttributes.begin(), m_ActiveVertexAttributes.end(), attributeLocation); + if (it == m_ActiveVertexAttributes.end() || *it != attributeLocation) + return; const GLint size = GLSizeFromFormat(format); const GLenum type = GLTypeFromFormat(format); + const GLboolean normalized = NormalizedFromFormat(format); glVertexAttribPointer( - (m_Device->GetCapabilities().computeShaders ? 3 : 8) + texture - GL_TEXTURE0, size, type, GL_FALSE, stride, pointer); - m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); - } - - void VertexAttribPointer(attrib_id_t id, const Renderer::Backend::Format format, GLboolean normalized, GLsizei stride, const void* pointer) override - { - std::map::iterator it = m_VertexAttribs.find(id); - if (it != m_VertexAttribs.end()) - { - const GLint size = GLSizeFromFormat(format); - const GLenum type = GLTypeFromFormat(format); - glVertexAttribPointer(it->second, size, type, normalized, stride, pointer); - m_ValidStreams |= STREAM_UV0 << (it->second - (m_Device->GetCapabilities().computeShaders ? 3 : 8)); - } + attributeLocation, size, type, normalized, stride, static_cast(data) + offset); + m_ValidStreams |= GetStreamMask(stream); } std::vector GetFileDependencies() const override @@ -941,29 +930,30 @@ if (attributeName.empty() && isGLSL) LOGERROR("Empty attribute name in vertex shader description '%s'", vertexFile.string8().c_str()); - int stream = 0; + VertexAttributeStream stream = + VertexAttributeStream::UV7; if (streamName == "pos") - stream = STREAM_POS; + stream = VertexAttributeStream::POSITION; else if (streamName == "normal") - stream = STREAM_NORMAL; + stream = VertexAttributeStream::NORMAL; else if (streamName == "color") - stream = STREAM_COLOR; + stream = VertexAttributeStream::COLOR; else if (streamName == "uv0") - stream = STREAM_UV0; + stream = VertexAttributeStream::UV0; else if (streamName == "uv1") - stream = STREAM_UV1; + stream = VertexAttributeStream::UV1; else if (streamName == "uv2") - stream = STREAM_UV2; + stream = VertexAttributeStream::UV2; else if (streamName == "uv3") - stream = STREAM_UV3; + stream = VertexAttributeStream::UV3; else if (streamName == "uv4") - stream = STREAM_UV4; + stream = VertexAttributeStream::UV4; else if (streamName == "uv5") - stream = STREAM_UV5; + stream = VertexAttributeStream::UV5; else if (streamName == "uv6") - stream = STREAM_UV6; + stream = VertexAttributeStream::UV6; else if (streamName == "uv7") - stream = STREAM_UV7; + stream = VertexAttributeStream::UV7; else LOGERROR("Unknown stream '%s' in vertex shader description '%s'", streamName.c_str(), vertexFile.string8().c_str()); @@ -972,7 +962,7 @@ const int attributeLocation = GetAttributeLocationFromStream(device, stream); vertexAttribs[CStrIntern(attributeName)] = attributeLocation; } - streamFlags |= stream; + streamFlags |= GetStreamMask(stream); } } } @@ -1061,11 +1051,6 @@ device, name, vertexFile, fragmentFile, defines, vertexAttribs, streamflags); } -int CShaderProgram::GetStreamFlags() const -{ - return m_StreamFlags; -} - void CShaderProgram::BindTexture(texture_id_t id, const Renderer::Backend::GL::CTexture* tex) { BindTexture(id, tex->GetHandle()); @@ -1190,14 +1175,14 @@ ENSURE(2 <= size && size <= 4); const GLenum type = GLTypeFromFormat(format); glVertexPointer(size, type, stride, pointer); - m_ValidStreams |= STREAM_POS; + m_ValidStreams |= GetStreamMask(VertexAttributeStream::POSITION); } void CShaderProgram::NormalPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer) { ENSURE(format == Renderer::Backend::Format::R32G32B32_SFLOAT); glNormalPointer(GL_FLOAT, stride, pointer); - m_ValidStreams |= STREAM_NORMAL; + m_ValidStreams |= GetStreamMask(VertexAttributeStream::NORMAL); } void CShaderProgram::ColorPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer) @@ -1206,7 +1191,7 @@ ENSURE(3 <= size && size <= 4); const GLenum type = GLTypeFromFormat(format); glColorPointer(size, type, stride, pointer); - m_ValidStreams |= STREAM_COLOR; + m_ValidStreams |= GetStreamMask(VertexAttributeStream::COLOR); } void CShaderProgram::TexCoordPointer(GLenum texture, const Renderer::Backend::Format format, GLsizei stride, const void* pointer) @@ -1217,26 +1202,34 @@ const GLenum type = GLTypeFromFormat(format); glTexCoordPointer(size, type, stride, pointer); glClientActiveTextureARB(GL_TEXTURE0); - m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); + m_ValidStreams |= GetStreamMask(VertexAttributeStream::UV0) << (texture - GL_TEXTURE0); } void CShaderProgram::BindClientStates() { - ENSURE(m_StreamFlags == (m_StreamFlags & (STREAM_POS|STREAM_NORMAL|STREAM_COLOR|STREAM_UV0|STREAM_UV1))); + ENSURE(m_StreamFlags == (m_StreamFlags & ( + GetStreamMask(VertexAttributeStream::POSITION) | + GetStreamMask(VertexAttributeStream::NORMAL) | + GetStreamMask(VertexAttributeStream::COLOR) | + GetStreamMask(VertexAttributeStream::UV0) | + GetStreamMask(VertexAttributeStream::UV1)))); // Enable all the desired client states for non-GLSL rendering - if (m_StreamFlags & STREAM_POS) glEnableClientState(GL_VERTEX_ARRAY); - if (m_StreamFlags & STREAM_NORMAL) glEnableClientState(GL_NORMAL_ARRAY); - if (m_StreamFlags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::POSITION)) + glEnableClientState(GL_VERTEX_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::NORMAL)) + glEnableClientState(GL_NORMAL_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::COLOR)) + glEnableClientState(GL_COLOR_ARRAY); - if (m_StreamFlags & STREAM_UV0) + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::UV0)) { glClientActiveTextureARB(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } - if (m_StreamFlags & STREAM_UV1) + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::UV1)) { glClientActiveTextureARB(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1251,17 +1244,20 @@ void CShaderProgram::UnbindClientStates() { - if (m_StreamFlags & STREAM_POS) glDisableClientState(GL_VERTEX_ARRAY); - if (m_StreamFlags & STREAM_NORMAL) glDisableClientState(GL_NORMAL_ARRAY); - if (m_StreamFlags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::POSITION)) + glDisableClientState(GL_VERTEX_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::NORMAL)) + glDisableClientState(GL_NORMAL_ARRAY); + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::COLOR)) + glDisableClientState(GL_COLOR_ARRAY); - if (m_StreamFlags & STREAM_UV0) + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::UV0)) { glClientActiveTextureARB(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } - if (m_StreamFlags & STREAM_UV1) + if (m_StreamFlags & GetStreamMask(VertexAttributeStream::UV1)) { glClientActiveTextureARB(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1271,6 +1267,44 @@ #endif // !CONFIG2_GLES +bool CShaderProgram::IsStreamActive(const VertexAttributeStream stream) const +{ + return (m_StreamFlags & GetStreamMask(stream)) != 0; +} + +void CShaderProgram::VertexAttribPointer( + const VertexAttributeStream stream, const Format format, + const uint32_t offset, const uint32_t stride, const void* data) +{ + switch (stream) + { + case VertexAttributeStream::POSITION: + VertexPointer(format, stride, static_cast(data) + offset); + break; + case VertexAttributeStream::NORMAL: + NormalPointer(format, stride, static_cast(data) + offset); + break; + case VertexAttributeStream::COLOR: + ColorPointer(format, stride, static_cast(data) + offset); + break; + case VertexAttributeStream::UV0: FALLTHROUGH; + case VertexAttributeStream::UV1: FALLTHROUGH; + case VertexAttributeStream::UV2: FALLTHROUGH; + case VertexAttributeStream::UV3: FALLTHROUGH; + case VertexAttributeStream::UV4: FALLTHROUGH; + case VertexAttributeStream::UV5: FALLTHROUGH; + case VertexAttributeStream::UV6: FALLTHROUGH; + case VertexAttributeStream::UV7: + { + const int indexOffset = static_cast(stream) - static_cast(VertexAttributeStream::UV0); + TexCoordPointer(GL_TEXTURE0 + indexOffset, format, stride, static_cast(data) + offset); + break; + } + default: + debug_warn("Unsupported stream"); + }; +} + void CShaderProgram::AssertPointersBound() { ENSURE((m_StreamFlags & ~m_ValidStreams) == 0);