Merge branch 'StreamBuffers'

This branch drops our temporary buffer in VertexLoaderBase.
Instead, every backend now must provide a buffer to convert vertices and indices.
D3D just uses a temporary buffer like before.
OGL maps the gpu based buffer and stream to them directly.
So this will avoid an unneeded memcpy on OGL backend.
This commit is contained in:
degasus
2014-01-23 18:40:56 +01:00
10 changed files with 426 additions and 314 deletions
@@ -77,6 +77,12 @@ void VertexManager::DestroyDeviceObjects()
VertexManager::VertexManager()
{
LocalVBuffer.resize(MAXVBUFFERSIZE);
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
LocalIBuffer.resize(MAXIBUFFERSIZE);
CreateDeviceObjects();
}
@@ -222,4 +228,10 @@ void VertexManager::vFlush()
g_renderer->RestoreState();
}
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer;
IndexGenerator::Start(GetIndexBuffer());
}
} // namespace
@@ -22,6 +22,10 @@ public:
void CreateDeviceObjects();
void DestroyDeviceObjects();
protected:
virtual void ResetBuffer(u32 stride);
u16* GetIndexBuffer() { return &LocalIBuffer[0]; }
private:
void PrepareDrawBuffers();
@@ -41,6 +45,9 @@ private:
LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader;
std::vector<u8> LocalVBuffer;
std::vector<u16> LocalIBuffer;
};
} // namespace
@@ -193,29 +193,19 @@ void ProgramShaderCache::UploadConstants()
{
if(PixelShaderManager::dirty || VertexShaderManager::dirty)
{
s_buffer->Alloc(s_ubo_buffer_size);
if (DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTREAM))
{
// This is just a hack to support our BUFFERDATA upload method
// as it's broken to uploaded in a splited way
static u8 *tmpbuffer = new u8[s_ubo_buffer_size];
memcpy(tmpbuffer, &PixelShaderManager::constants, sizeof(PixelShaderConstants));
memcpy(tmpbuffer+ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align), &VertexShaderManager::constants, sizeof(VertexShaderConstants));
size_t offset = s_buffer->Upload(tmpbuffer, s_ubo_buffer_size);
glBindBufferRange(GL_UNIFORM_BUFFER, 1,
s_buffer->getBuffer(), offset, sizeof(PixelShaderConstants));
glBindBufferRange(GL_UNIFORM_BUFFER, 2,
s_buffer->getBuffer(), offset+ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align), sizeof(VertexShaderConstants));
}
else
{
size_t offset = s_buffer->Upload((u8*)&PixelShaderManager::constants, ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align));
glBindBufferRange(GL_UNIFORM_BUFFER, 1,
s_buffer->getBuffer(), offset, sizeof(PixelShaderConstants));
offset = s_buffer->Upload((u8*)&VertexShaderManager::constants, ROUND_UP(sizeof(VertexShaderConstants), s_ubo_align));
glBindBufferRange(GL_UNIFORM_BUFFER, 2,
s_buffer->getBuffer(), offset, sizeof(VertexShaderConstants));
}
auto buffer = s_buffer->Map(s_ubo_buffer_size, s_ubo_align);
memcpy(buffer.first,
&PixelShaderManager::constants, sizeof(PixelShaderConstants));
memcpy(buffer.first + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align),
&VertexShaderManager::constants, sizeof(VertexShaderConstants));
s_buffer->Unmap(s_ubo_buffer_size);
glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->m_buffer, buffer.second,
sizeof(PixelShaderConstants));
glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer, buffer.second + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align),
sizeof(VertexShaderConstants));
PixelShaderManager::dirty = false;
VertexShaderManager::dirty = false;
@@ -481,7 +471,7 @@ void ProgramShaderCache::Init(void)
// We multiply by *4*4 because we need to get down to basic machine units.
// So multiply by four to get how many floats we have from vec4s
// Then once more to get bytes
s_buffer = new StreamBuffer(GL_UNIFORM_BUFFER, UBO_LENGTH);
s_buffer = StreamBuffer::Create(GL_UNIFORM_BUFFER, UBO_LENGTH);
}
// Read our shader cache, only if supported
+1 -1
View File
@@ -1653,7 +1653,7 @@ void Renderer::RestoreAPIState()
VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
vm->m_last_vao = 0;
glBindVertexArray(vm->m_last_vao);
TextureCache::SetStage();
}
File diff suppressed because it is too large Load Diff
+26 -23
View File
@@ -5,6 +5,7 @@
#ifndef STREAMBUFFER_H
#define STREAMBUFFER_H
#include <utility>
#include "VideoCommon.h"
#include "FramebufferManager.h"
#include "GLUtil.h"
@@ -17,39 +18,41 @@
namespace OGL
{
enum StreamType {
MAP_AND_ORPHAN = (1 << 1),
MAP_AND_SYNC = (1 << 2),
PINNED_MEMORY = (1 << 3),
BUFFERSUBDATA = (1 << 4),
BUFFERDATA = (1 << 5),
BUFFERSTORAGE = (1 << 6),
};
class StreamBuffer {
public:
static StreamBuffer* Create(u32 type, size_t size);
virtual ~StreamBuffer();
/* This mapping function will return a pair of:
* - the pointer to the mapped buffer
* - the offset into the real gpu buffer (always multiple of stride)
* On mapping, the maximum of size for allocation has to be set.
* The size really pushed into this fifo only has to be known on Unmapping.
* Mapping invalidates the current buffer content,
* so it isn't allowed to access the old content any more.
*/
virtual std::pair<u8*, size_t> Map(size_t size, u32 stride = 0) = 0;
virtual void Unmap(size_t used_size) = 0;
const u32 m_buffer;
protected:
StreamBuffer(u32 type, size_t size);
~StreamBuffer();
void Alloc(size_t size, u32 stride = 0);
size_t Upload(u8 *data, size_t size);
u32 getBuffer() { return m_buffer; }
private:
void Init();
void Shutdown();
void CreateFences();
void DeleteFences();
void AllocMemory(size_t size);
void Align(u32 stride);
StreamType m_uploadtype;
u32 m_buffer;
u32 m_buffertype;
size_t m_size;
u8 *pointer;
const u32 m_buffertype;
const size_t m_size;
size_t m_iterator;
size_t m_used_iterator;
size_t m_free_iterator;
private:
GLsync *fences;
};
+20 -11
View File
@@ -39,7 +39,7 @@ namespace OGL
{
//This are the initially requested size for the buffers expressed in bytes
const u32 MAX_IBUFFER_SIZE = 2*1024*1024;
const u32 MAX_VBUFFER_SIZE = 16*1024*1024;
const u32 MAX_VBUFFER_SIZE = 32*1024*1024;
static StreamBuffer *s_vertexBuffer;
static StreamBuffer *s_indexBuffer;
@@ -58,11 +58,11 @@ VertexManager::~VertexManager()
void VertexManager::CreateDeviceObjects()
{
s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
m_vertex_buffers = s_vertexBuffer->getBuffer();
s_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
m_vertex_buffers = s_vertexBuffer->m_buffer;
s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
m_index_buffers = s_indexBuffer->getBuffer();
s_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
m_index_buffers = s_indexBuffer->m_buffer;
m_CurrentVertexFmt = NULL;
m_last_vao = 0;
@@ -85,17 +85,25 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);
s_vertexBuffer->Alloc(vertex_data_size, stride);
size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size);
s_baseVertex = offset / stride;
s_indexBuffer->Alloc(index_data_size);
s_index_offset = s_indexBuffer->Upload((u8*)GetIndexBuffer(), index_data_size);
s_vertexBuffer->Unmap(vertex_data_size);
s_indexBuffer->Unmap(index_data_size);
ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size);
ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
}
void VertexManager::ResetBuffer(u32 stride)
{
auto buffer = s_vertexBuffer->Map(MAXVBUFFERSIZE, stride);
s_pCurBufferPointer = s_pBaseBufferPointer = buffer.first;
s_pEndBufferPointer = buffer.first + MAXVBUFFERSIZE;
s_baseVertex = buffer.second / stride;
buffer = s_indexBuffer->Map(MAXIBUFFERSIZE * sizeof(u16));
IndexGenerator::Start((u16*)buffer.first);
s_index_offset = buffer.second;
}
void VertexManager::Draw(u32 stride)
{
u32 index_size = IndexGenerator::GetIndexLen();
@@ -234,4 +242,5 @@ void VertexManager::vFlush()
GL_REPORT_ERRORD();
}
} // namespace
@@ -40,6 +40,8 @@ public:
GLuint m_vertex_buffers;
GLuint m_index_buffers;
GLuint m_last_vao;
protected:
virtual void ResetBuffer(u32 stride);
private:
void Draw(u32 stride);
void vFlush() override;
+11 -34
View File
@@ -24,6 +24,8 @@ u8 *VertexManager::s_pEndBufferPointer;
PrimitiveType VertexManager::current_primitive_type;
bool VertexManager::IsFlushed;
static const PrimitiveType primitive_from_gx[8] = {
PRIMITIVE_TRIANGLES, // GX_DRAW_QUADS
PRIMITIVE_TRIANGLES, // GX_DRAW_NONE
@@ -37,25 +39,13 @@ static const PrimitiveType primitive_from_gx[8] = {
VertexManager::VertexManager()
{
LocalVBuffer.resize(MAXVBUFFERSIZE);
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
LocalIBuffer.resize(MAXIBUFFERSIZE);
ResetBuffer();
IsFlushed = true;
}
VertexManager::~VertexManager()
{
}
void VertexManager::ResetBuffer()
{
s_pCurBufferPointer = s_pBaseBufferPointer;
IndexGenerator::Start(GetIndexBuffer());
}
u32 VertexManager::GetRemainingSize()
{
return (u32)(s_pEndBufferPointer - s_pCurBufferPointer);
@@ -84,11 +74,13 @@ void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 strid
ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! "
"Increase MAXVBUFFERSIZE or we need primitive breaking after all.");
}
}
bool VertexManager::IsFlushed() const
{
return s_pBaseBufferPointer == s_pCurBufferPointer;
// need to alloc new buffer
if(IsFlushed)
{
g_vertex_manager->ResetBuffer(stride);
IsFlushed = false;
}
}
u32 VertexManager::GetRemainingIndices(int primitive)
@@ -160,8 +152,7 @@ void VertexManager::AddVertices(int primitive, u32 numVertices)
void VertexManager::Flush()
{
if (g_vertex_manager->IsFlushed())
return;
if (IsFlushed) return;
// loading a state will invalidate BP, so check for it
g_video_backend->CheckInvalidState();
@@ -238,24 +229,10 @@ void VertexManager::Flush()
// TODO: need to merge more stuff into VideoCommon
g_vertex_manager->vFlush();
g_vertex_manager->ResetBuffer();
IsFlushed = true;
}
void VertexManager::DoState(PointerWrap& p)
{
g_vertex_manager->vDoState(p);
}
void VertexManager::DoStateShared(PointerWrap& p)
{
// It seems we half-assume to be flushed here
// We update s_pCurBufferPointer yet don't worry about IndexGenerator's outdated pointers
// and maybe other things are overlooked
p.Do(LocalVBuffer);
p.Do(LocalIBuffer);
s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer);
}
+4 -11
View File
@@ -51,25 +51,18 @@ public:
virtual void DestroyDeviceObjects(){};
protected:
u16* GetIndexBuffer() { return &LocalIBuffer[0]; }
u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; }
virtual void vDoState(PointerWrap& p) { DoStateShared(p); }
void DoStateShared(PointerWrap& p);
virtual void vDoState(PointerWrap& p) { }
static PrimitiveType current_primitive_type;
private:
bool IsFlushed() const;
virtual void ResetBuffer(u32 stride) = 0;
void ResetBuffer();
private:
static bool IsFlushed;
//virtual void Draw(u32 stride, bool alphapass) = 0;
// temp
virtual void vFlush() = 0;
std::vector<u8> LocalVBuffer;
std::vector<u16> LocalIBuffer;
};
extern VertexManager *g_vertex_manager;