From 78417f6cdedfcf60c8ca437190975644e942e01f Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 1 Nov 2021 10:43:51 +0800 Subject: *rename SharedVertexBuffer -> DynamicVertexBuffer --- Runtime/Graphics/DynamicVertexBuffer.cpp | 267 +++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 Runtime/Graphics/DynamicVertexBuffer.cpp (limited to 'Runtime/Graphics/DynamicVertexBuffer.cpp') diff --git a/Runtime/Graphics/DynamicVertexBuffer.cpp b/Runtime/Graphics/DynamicVertexBuffer.cpp new file mode 100644 index 0000000..203aa26 --- /dev/null +++ b/Runtime/Graphics/DynamicVertexBuffer.cpp @@ -0,0 +1,267 @@ +#include "DynamicVertexBuffer.h" +#include "../Profiling/FrameStats.h" + +DynamicVertexBuffer::DynamicVertexBuffer() +{ +} + +DynamicVertexBuffer::~DynamicVertexBuffer() +{ +} + +//------------------------------------------------------------------------------------------------------------ +// Defualt Vertex Layout + +//GetChunk +//-> ReleaseChunk +//-> DrawChunk + +void DynamicVertexBuffer::GetChunk(uint attrsMask, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib) +{ + Assert(out_vb && out_ib); + + uint stride = VertexLayout::GetDynamicChunkStride(attrsMask); // data size of single vertex + GetChunk(stride, maxVerts, VertexLayout::GetDefaultIndexSize(), maxIndices, primitive, out_vb, out_ib); + + // default layout + m_CurAttrMask = attrsMask; + m_CurStride = stride; +} + +void DynamicVertexBuffer::DrawChunk() +{ + DefaultVertexLayout vertexArray; + FillDefaultVertexLayout(vertexArray); + + // bind vertex attributes data + VertexLayout::SetupDefaultVertexLayout(vertexArray); + + const void* indexPtr = m_CurIB ? 0 : (m_CurIBData.empty() ? 0 : &m_CurIBData[0]); + + if (m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CurIB->GetHandle()); + + GLenum indexFormat = VertexLayout::GetDefaultIndexFormat(); + + switch (m_CurPrimitive) + { + case Primitive_Triangle: + glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + g_FrameStats.AddTrianglesCount(m_CurIndexCount / 3); + break; + case Primitive_Line: + glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + case Primitive_Point: + glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + } + + if (m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // End draw + Clean(); +} + +void DynamicVertexBuffer::FillDefaultVertexLayout(DefaultVertexLayout& dst) +{ + const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0]; + const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0; + + int attrOffsets[VertexAttr_Count] = { 0 }; + { + uint32 curOffset = 0; + for (uint idx = 0; idx < VertexAttr_Count; ++idx) + { + if (m_CurAttrMask & Mask(idx)) + { + attrOffsets[idx] = curOffset; + curOffset += VertexLayout::GetDefaultVertexAttrSize(idx); + } + } + } + + dst.buffer = buffer; + + for (uint32 attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx) + { + if (m_CurAttrMask & Mask(attrIdx)) + { + dst.attributes[attrIdx].pointer = basepointer + attrOffsets[attrIdx]; + dst.attributes[attrIdx].componentFormat = VertexLayout::GetDefaultShaderChannelFormat(attrIdx); + dst.attributes[attrIdx].componentNum = VertexLayout::GetDefaultShaderChannelDimension(attrIdx); + dst.attributes[attrIdx].stride = m_CurStride; + + dst.enableMask |= Mask(attrIdx); + } + } +} + +//------------------------------------------------------------------------------------------------------------ +// Custom Vertex Layout + +// 用buffersize为依据决定用vbo或者pinned memory +void DynamicVertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib) +{ + Assert(out_vb && out_ib); + + uint vbufferSize = sizePerVert * maxVerts; + uint ibufferSize = sizePerIndex * maxIndices; + + const bool mapVertexBuffer = vbufferSize >= DataBufferThreshold; + const bool mapIndexBuffer = ibufferSize >= DataBufferThreshold; + + GLenum usage = GL_STREAM_DRAW; + + GPU::DataBuffer* vertexBuffer = mapVertexBuffer ? GPU::ClaimBuffer(vbufferSize, usage) : 0; + GPU::DataBuffer* indexBuffer = mapIndexBuffer ? GPU::ClaimBuffer(ibufferSize, usage) : 0; + + if (vertexBuffer && vertexBuffer->GetSize() < vbufferSize) + vertexBuffer->Restore(vbufferSize, usage); + + if (indexBuffer && indexBuffer->GetSize() < ibufferSize) + indexBuffer->Restore(ibufferSize, usage); + + if (!mapVertexBuffer && m_CurVBData.size() < vbufferSize) + m_CurVBData.resize(vbufferSize); + + if (!mapIndexBuffer && m_CurIBData.size() < ibufferSize) + m_CurIBData.resize(ibufferSize); + + const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + + if (vertexBuffer) + *out_vb = vertexBuffer->MapRange(0, vbufferSize, access); + else + *out_vb = &m_CurVBData[0]; + + if (indexBuffer) + *out_ib = indexBuffer->MapRange(0, ibufferSize, access); + else + *out_ib = &m_CurIBData[0]; + + m_CurVB = vertexBuffer; + m_CurIB = indexBuffer; + + m_CurPrimitive = primitive; +} + +void DynamicVertexBuffer::FillCustomVertexLayout(CustomVertexLayout& dst) +{ + const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0]; + const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0; + + dst.buffer = buffer; + + for (int i = 0; i < dst.attributes.size(); ++i) + { + int offset = dst.attributes[i].startOffset; + dst.attributes[i].pointer = basepointer + offset; + } +} + +void DynamicVertexBuffer::DrawChunk(CustomVertexLayout& layout) +{ + const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0]; + const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0; + + FillCustomVertexLayout(layout); + + VertexLayout::SetupCustomVertexLayout(layout); + + layout.RestorePointer(); + + const void* indexPtr = m_CurIB ? 0 : (m_CurIBData.empty() ? 0 : &m_CurIBData[0]); + + if (m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CurIB->GetHandle()); + + GLenum indexFormat = VertexLayout::GetDefaultIndexFormat(); + + switch (m_CurPrimitive) + { + case Primitive_Triangle: + glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + g_FrameStats.AddTrianglesCount(m_CurIndexCount / 3); + break; + case Primitive_Line: + glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + case Primitive_Point: + glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + } + + if (m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // End draw + Clean(); +} + +//------------------------------------------------------------------------------------------------------------ +// Both Default and Custom Vertex Layout + +void DynamicVertexBuffer::ReleaseChunk(int actualVerts, int actualIndices) +{ + int actualVBufferSize = m_CurStride * actualVerts; + int actualIBufferSize = VertexLayout::GetDefaultIndexSize() * actualIndices; + + const GLenum usage = GL_STREAM_DRAW; + + if (m_CurVB) + { + m_CurVB->FlushMapedRange(0, actualVBufferSize); + m_CurVB->UnMap(); + } + else if (actualVBufferSize >= DataBufferThreshold) + { + m_CurVB = GPU::ClaimBuffer(actualVBufferSize, usage); + m_CurVB->RestoreWithData(actualVBufferSize, usage, &m_CurVBData[0]); + } + + if (m_CurIB) + { + m_CurIB->FlushMapedRange(0, actualIBufferSize); + m_CurIB->UnMap(); + } + else if (actualIBufferSize >= DataBufferThreshold) + { + m_CurIB = GPU::ClaimBuffer(0, usage); + m_CurIB->RestoreWithData(0, usage, &m_CurIBData[0]); + } + + m_CurVertexCount = actualVerts; + m_CurIndexCount = actualIndices; +} + +void DynamicVertexBuffer::Clean() +{ + if (m_CurVB) + { + GPU::ReleaseBuffer(m_CurVB); + m_CurVB = 0; + } + + if (m_CurIB) + { + GPU::ReleaseBuffer(m_CurIB); + m_CurIB = 0; + } + + m_CurPrimitive = Primitive_Triangle; + m_CurAttrMask = 0; + m_CurStride = 0; + m_CurVertexCount = 0; + m_CurIndexCount = 0; + + m_CurVBData.clear(); + m_CurIBData.clear(); +} -- cgit v1.1-26-g67d0