diff options
| author | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
|---|---|---|
| committer | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
| commit | 7dfced21a2e5aac7195e0e1ad76468e30306766b (patch) | |
| tree | bd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/VideoBackends/OGL/VertexManager.cpp | |
| parent | c25be031fc1031d795157d8344b87b7841145197 (diff) | |
| parent | 7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff) | |
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/VideoBackends/OGL/VertexManager.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/OGL/VertexManager.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp new file mode 100644 index 0000000000..b203cd3e7d --- /dev/null +++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp @@ -0,0 +1,229 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <fstream> +#include <string> +#include <vector> + +#include "Common/FileUtil.h" +#include "Common/MemoryUtil.h" +#include "Common/StringUtil.h" + +#include "VideoBackends/OGL/main.h" +#include "VideoBackends/OGL/ProgramShaderCache.h" +#include "VideoBackends/OGL/Render.h" +#include "VideoBackends/OGL/StreamBuffer.h" +#include "VideoBackends/OGL/TextureCache.h" +#include "VideoBackends/OGL/VertexManager.h" + +#include "VideoCommon/BPMemory.h" +#include "VideoCommon/DriverDetails.h" +#include "VideoCommon/Fifo.h" +#include "VideoCommon/ImageWrite.h" +#include "VideoCommon/IndexGenerator.h" +#include "VideoCommon/PixelShaderManager.h" +#include "VideoCommon/Statistics.h" +#include "VideoCommon/VertexLoaderManager.h" +#include "VideoCommon/VertexShaderGen.h" +#include "VideoCommon/VertexShaderManager.h" +#include "VideoCommon/VideoConfig.h" + +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 = 32*1024*1024; + +static StreamBuffer *s_vertexBuffer; +static StreamBuffer *s_indexBuffer; +static size_t s_baseVertex; +static size_t s_index_offset; + +VertexManager::VertexManager() + : m_cpu_v_buffer(MAX_VBUFFER_SIZE), m_cpu_i_buffer(MAX_IBUFFER_SIZE) +{ + CreateDeviceObjects(); +} + +VertexManager::~VertexManager() +{ + DestroyDeviceObjects(); +} + +void VertexManager::CreateDeviceObjects() +{ + s_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE); + m_vertex_buffers = s_vertexBuffer->m_buffer; + + s_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE); + m_index_buffers = s_indexBuffer->m_buffer; + + m_last_vao = 0; +} + +void VertexManager::DestroyDeviceObjects() +{ + delete s_vertexBuffer; + delete s_indexBuffer; +} + +void VertexManager::PrepareDrawBuffers(u32 stride) +{ + u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride; + u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16); + + 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) +{ + if (s_cull_all) + { + // This buffer isn't getting sent to the GPU. Just allocate it on the cpu. + s_pCurBufferPointer = s_pBaseBufferPointer = m_cpu_v_buffer.data(); + s_pEndBufferPointer = s_pBaseBufferPointer + m_cpu_v_buffer.size(); + + IndexGenerator::Start((u16*)m_cpu_i_buffer.data()); + } + else + { + 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(); + u32 max_index = IndexGenerator::GetNumVerts(); + GLenum primitive_mode = 0; + + switch (current_primitive_type) + { + case PRIMITIVE_POINTS: + primitive_mode = GL_POINTS; + glDisable(GL_CULL_FACE); + break; + case PRIMITIVE_LINES: + primitive_mode = GL_LINES; + glDisable(GL_CULL_FACE); + break; + case PRIMITIVE_TRIANGLES: + primitive_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? GL_TRIANGLE_STRIP : GL_TRIANGLES; + break; + } + + if (g_ogl_config.bSupportsGLBaseVertex) + { + glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr+s_index_offset, (GLint)s_baseVertex); + } + else + { + glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr+s_index_offset); + } + + INCSTAT(stats.thisFrame.numDrawCalls); + + if (current_primitive_type != PRIMITIVE_TRIANGLES) + ((OGL::Renderer*)g_renderer)->SetGenerationMode(); +} + +void VertexManager::vFlush(bool useDstAlpha) +{ + GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat(); + u32 stride = nativeVertexFmt->GetVertexStride(); + + if (m_last_vao != nativeVertexFmt->VAO) + { + glBindVertexArray(nativeVertexFmt->VAO); + m_last_vao = nativeVertexFmt->VAO; + } + + PrepareDrawBuffers(stride); + + // Makes sure we can actually do Dual source blending + bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend; + + // If host supports GL_ARB_blend_func_extended, we can do dst alpha in + // the same pass as regular rendering. + if (useDstAlpha && dualSourcePossible) + { + ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, nativeVertexFmt->m_components, current_primitive_type); + } + else + { + ProgramShaderCache::SetShader(DSTALPHA_NONE, nativeVertexFmt->m_components, current_primitive_type); + } + + // upload global constants + ProgramShaderCache::UploadConstants(); + + // setup the pointers + nativeVertexFmt->SetupVertexPointers(); + + Draw(stride); + + // run through vertex groups again to set alpha + if (useDstAlpha && !dualSourcePossible) + { + ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, nativeVertexFmt->m_components, current_primitive_type); + + // only update alpha + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + + glDisable(GL_BLEND); + + Draw(stride); + + // restore color mask + g_renderer->SetColorMask(); + + if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract) + glEnable(GL_BLEND); + } + +#if defined(_DEBUG) || defined(DEBUGFAST) + if (g_ActiveConfig.iLog & CONF_SAVESHADERS) + { + // save the shaders + ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram(); + std::string filename = StringFromFormat("%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + std::ofstream fps; + OpenFStream(fps, filename, std::ios_base::out); + fps << prog.shader.strpprog.c_str(); + + filename = StringFromFormat("%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + std::ofstream fvs; + OpenFStream(fvs, filename, std::ios_base::out); + fvs << prog.shader.strvprog.c_str(); + } + + if (g_ActiveConfig.iLog & CONF_SAVETARGETS) + { + std::string filename = StringFromFormat("%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + TargetRectangle tr; + tr.left = 0; + tr.right = Renderer::GetTargetWidth(); + tr.top = 0; + tr.bottom = Renderer::GetTargetHeight(); + g_renderer->SaveScreenshot(filename, tr); + } +#endif + g_Config.iSaveTargetId++; + + ClearEFBCache(); +} + + +} // namespace |
