summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Markus Wick2018-08-09 21:31:46 +0200
committerGravatar Markus Wick2018-08-12 15:47:35 +0200
commitd7298ec2626f013167ea254276259ac7b39f46be (patch)
treec011140a61d25b1f93894b9ed7d683e54b1b8e06 /src
parentMerge pull request #1029 from bunnei/fix-out-attrib (diff)
downloadyuzu-d7298ec2626f013167ea254276259ac7b39f46be.tar.gz
yuzu-d7298ec2626f013167ea254276259ac7b39f46be.tar.xz
yuzu-d7298ec2626f013167ea254276259ac7b39f46be.zip
Update the stream_buffer helper from Citra.
Please see https://github.com/citra-emu/citra/pull/3666 for more details.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp36
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp201
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.h42
4 files changed, 98 insertions, 184 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 38a7b1413..94e3f59a7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -36,7 +36,8 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
36MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); 36MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
37MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); 37MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
38 38
39RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window) : emu_window{window} { 39RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window)
40 : emu_window{window}, stream_buffer(GL_ARRAY_BUFFER, STREAM_BUFFER_SIZE) {
40 // Create sampler objects 41 // Create sampler objects
41 for (size_t i = 0; i < texture_samplers.size(); ++i) { 42 for (size_t i = 0; i < texture_samplers.size(); ++i) {
42 texture_samplers[i].Create(); 43 texture_samplers[i].Create();
@@ -57,9 +58,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window) : emu_wind
57 const std::string_view extension{ 58 const std::string_view extension{
58 reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))}; 59 reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))};
59 60
60 if (extension == "GL_ARB_buffer_storage") { 61 if (extension == "GL_ARB_direct_state_access") {
61 has_ARB_buffer_storage = true;
62 } else if (extension == "GL_ARB_direct_state_access") {
63 has_ARB_direct_state_access = true; 62 has_ARB_direct_state_access = true;
64 } else if (extension == "GL_ARB_separate_shader_objects") { 63 } else if (extension == "GL_ARB_separate_shader_objects") {
65 has_ARB_separate_shader_objects = true; 64 has_ARB_separate_shader_objects = true;
@@ -86,16 +85,14 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window) : emu_wind
86 85
87 hw_vao.Create(); 86 hw_vao.Create();
88 87
89 stream_buffer = OGLStreamBuffer::MakeBuffer(has_ARB_buffer_storage, GL_ARRAY_BUFFER); 88 state.draw.vertex_buffer = stream_buffer.GetHandle();
90 stream_buffer->Create(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE / 2);
91 state.draw.vertex_buffer = stream_buffer->GetHandle();
92 89
93 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 90 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
94 state.draw.shader_program = 0; 91 state.draw.shader_program = 0;
95 state.draw.vertex_array = hw_vao.handle; 92 state.draw.vertex_array = hw_vao.handle;
96 state.Apply(); 93 state.Apply();
97 94
98 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle()); 95 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer.GetHandle());
99 96
100 for (unsigned index = 0; index < uniform_buffers.size(); ++index) { 97 for (unsigned index = 0; index < uniform_buffers.size(); ++index) {
101 auto& buffer = uniform_buffers[index]; 98 auto& buffer = uniform_buffers[index];
@@ -111,13 +108,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window) : emu_wind
111 LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!"); 108 LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
112} 109}
113 110
114RasterizerOpenGL::~RasterizerOpenGL() { 111RasterizerOpenGL::~RasterizerOpenGL() {}
115 if (stream_buffer != nullptr) {
116 state.draw.vertex_buffer = stream_buffer->GetHandle();
117 state.Apply();
118 stream_buffer->Release();
119 }
120}
121 112
122std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, 113std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
123 GLintptr buffer_offset) { 114 GLintptr buffer_offset) {
@@ -126,7 +117,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
126 const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager; 117 const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager;
127 118
128 state.draw.vertex_array = hw_vao.handle; 119 state.draw.vertex_array = hw_vao.handle;
129 state.draw.vertex_buffer = stream_buffer->GetHandle(); 120 state.draw.vertex_buffer = stream_buffer.GetHandle();
130 state.Apply(); 121 state.Apply();
131 122
132 // Upload all guest vertex arrays sequentially to our buffer 123 // Upload all guest vertex arrays sequentially to our buffer
@@ -145,7 +136,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
145 Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size); 136 Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size);
146 137
147 // Bind the vertex array to the buffer at the current offset. 138 // Bind the vertex array to the buffer at the current offset.
148 glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride); 139 glBindVertexBuffer(index, stream_buffer.GetHandle(), buffer_offset, vertex_array.stride);
149 140
150 ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented"); 141 ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented");
151 142
@@ -205,7 +196,7 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
205 // Helper function for uploading uniform data 196 // Helper function for uploading uniform data
206 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { 197 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
207 if (has_ARB_direct_state_access) { 198 if (has_ARB_direct_state_access) {
208 glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size); 199 glCopyNamedBufferSubData(stream_buffer.GetHandle(), handle, offset, 0, size);
209 } else { 200 } else {
210 glBindBuffer(GL_COPY_WRITE_BUFFER, handle); 201 glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
211 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size); 202 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
@@ -456,7 +447,7 @@ void RasterizerOpenGL::DrawArrays() {
456 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()}; 447 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
457 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count}; 448 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
458 449
459 state.draw.vertex_buffer = stream_buffer->GetHandle(); 450 state.draw.vertex_buffer = stream_buffer.GetHandle();
460 state.Apply(); 451 state.Apply();
461 452
462 size_t buffer_size = CalculateVertexArraysSize(); 453 size_t buffer_size = CalculateVertexArraysSize();
@@ -471,8 +462,8 @@ void RasterizerOpenGL::DrawArrays() {
471 462
472 u8* buffer_ptr; 463 u8* buffer_ptr;
473 GLintptr buffer_offset; 464 GLintptr buffer_offset;
474 std::tie(buffer_ptr, buffer_offset) = 465 std::tie(buffer_ptr, buffer_offset, std::ignore) =
475 stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4); 466 stream_buffer.Map(static_cast<GLsizeiptr>(buffer_size), 4);
476 467
477 u8* offseted_buffer; 468 u8* offseted_buffer;
478 std::tie(offseted_buffer, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset); 469 std::tie(offseted_buffer, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset);
@@ -500,7 +491,8 @@ void RasterizerOpenGL::DrawArrays() {
500 491
501 SetupShaders(offseted_buffer, buffer_offset); 492 SetupShaders(offseted_buffer, buffer_offset);
502 493
503 stream_buffer->Unmap(); 494 // TODO: Don't use buffer_size here, use the updated buffer_offset.
495 stream_buffer.Unmap(buffer_size);
504 496
505 shader_program_manager->ApplyTo(state); 497 shader_program_manager->ApplyTo(state);
506 state.Apply(); 498 state.Apply();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bd01dc0ae..19146777c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -139,7 +139,6 @@ private:
139 /// Syncs the blend state to match the guest state 139 /// Syncs the blend state to match the guest state
140 void SyncBlendState(); 140 void SyncBlendState();
141 141
142 bool has_ARB_buffer_storage = false;
143 bool has_ARB_direct_state_access = false; 142 bool has_ARB_direct_state_access = false;
144 bool has_ARB_separate_shader_objects = false; 143 bool has_ARB_separate_shader_objects = false;
145 bool has_ARB_vertex_attrib_binding = false; 144 bool has_ARB_vertex_attrib_binding = false;
@@ -160,7 +159,7 @@ private:
160 ssbos; 159 ssbos;
161 160
162 static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 161 static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
163 std::unique_ptr<OGLStreamBuffer> stream_buffer; 162 OGLStreamBuffer stream_buffer;
164 OGLBuffer uniform_buffer; 163 OGLBuffer uniform_buffer;
165 OGLFramebuffer framebuffer; 164 OGLFramebuffer framebuffer;
166 165
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index a2713e9f0..03a8ed8b7 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -9,174 +9,91 @@
9#include "video_core/renderer_opengl/gl_state.h" 9#include "video_core/renderer_opengl/gl_state.h"
10#include "video_core/renderer_opengl/gl_stream_buffer.h" 10#include "video_core/renderer_opengl/gl_stream_buffer.h"
11 11
12class OrphanBuffer : public OGLStreamBuffer { 12OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent)
13public: 13 : gl_target(target), buffer_size(size) {
14 explicit OrphanBuffer(GLenum target) : OGLStreamBuffer(target) {} 14 gl_buffer.Create();
15 ~OrphanBuffer() override; 15 glBindBuffer(gl_target, gl_buffer.handle);
16
17private:
18 void Create(size_t size, size_t sync_subdivide) override;
19 void Release() override;
20
21 std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) override;
22 void Unmap() override;
23
24 std::vector<u8> data;
25};
26
27class StorageBuffer : public OGLStreamBuffer {
28public:
29 explicit StorageBuffer(GLenum target) : OGLStreamBuffer(target) {}
30 ~StorageBuffer() override;
31
32private:
33 void Create(size_t size, size_t sync_subdivide) override;
34 void Release() override;
35
36 std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) override;
37 void Unmap() override;
38
39 struct Fence {
40 OGLSync sync;
41 size_t offset;
42 };
43 std::deque<Fence> head;
44 std::deque<Fence> tail;
45
46 u8* mapped_ptr;
47};
48
49OGLStreamBuffer::OGLStreamBuffer(GLenum target) {
50 gl_target = target;
51}
52
53GLuint OGLStreamBuffer::GetHandle() const {
54 return gl_buffer.handle;
55}
56 16
57std::unique_ptr<OGLStreamBuffer> OGLStreamBuffer::MakeBuffer(bool storage_buffer, GLenum target) { 17 GLsizeiptr allocate_size = size;
58 if (storage_buffer) { 18 if (target == GL_ARRAY_BUFFER) {
59 return std::make_unique<StorageBuffer>(target); 19 // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer
20 // read position is near the end and is an out-of-bound access to the vertex buffer. This is
21 // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
22 // vertex array. Doubling the allocation size for the vertex buffer seems to avoid the
23 // crash.
24 allocate_size *= 2;
60 } 25 }
61 return std::make_unique<OrphanBuffer>(target);
62}
63 26
64OrphanBuffer::~OrphanBuffer() { 27 if (GLAD_GL_ARB_buffer_storage) {
65 Release(); 28 persistent = true;
29 coherent = prefer_coherent;
30 GLbitfield flags =
31 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
32 glBufferStorage(gl_target, allocate_size, nullptr, flags);
33 mapped_ptr = static_cast<u8*>(glMapBufferRange(
34 gl_target, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)));
35 } else {
36 glBufferData(gl_target, allocate_size, nullptr, GL_STREAM_DRAW);
37 }
66} 38}
67 39
68void OrphanBuffer::Create(size_t size, size_t /*sync_subdivide*/) { 40OGLStreamBuffer::~OGLStreamBuffer() {
69 buffer_pos = 0; 41 if (persistent) {
70 buffer_size = size;
71 data.resize(buffer_size);
72
73 if (gl_buffer.handle == 0) {
74 gl_buffer.Create();
75 glBindBuffer(gl_target, gl_buffer.handle); 42 glBindBuffer(gl_target, gl_buffer.handle);
43 glUnmapBuffer(gl_target);
76 } 44 }
77
78 glBufferData(gl_target, static_cast<GLsizeiptr>(buffer_size), nullptr, GL_STREAM_DRAW);
79}
80
81void OrphanBuffer::Release() {
82 gl_buffer.Release(); 45 gl_buffer.Release();
83} 46}
84 47
85std::pair<u8*, GLintptr> OrphanBuffer::Map(size_t size, size_t alignment) { 48GLuint OGLStreamBuffer::GetHandle() const {
86 buffer_pos = Common::AlignUp(buffer_pos, alignment); 49 return gl_buffer.handle;
87
88 if (buffer_pos + size > buffer_size) {
89 Create(std::max(buffer_size, size), 0);
90 }
91
92 mapped_size = size;
93 return std::make_pair(&data[buffer_pos], static_cast<GLintptr>(buffer_pos));
94}
95
96void OrphanBuffer::Unmap() {
97 glBufferSubData(gl_target, static_cast<GLintptr>(buffer_pos),
98 static_cast<GLsizeiptr>(mapped_size), &data[buffer_pos]);
99 buffer_pos += mapped_size;
100}
101
102StorageBuffer::~StorageBuffer() {
103 Release();
104} 50}
105 51
106void StorageBuffer::Create(size_t size, size_t sync_subdivide) { 52GLsizeiptr OGLStreamBuffer::GetSize() const {
107 if (gl_buffer.handle != 0) 53 return buffer_size;
108 return;
109
110 buffer_pos = 0;
111 buffer_size = size;
112 buffer_sync_subdivide = std::max<size_t>(sync_subdivide, 1);
113
114 gl_buffer.Create();
115 glBindBuffer(gl_target, gl_buffer.handle);
116
117 glBufferStorage(gl_target, static_cast<GLsizeiptr>(buffer_size), nullptr,
118 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
119 mapped_ptr = reinterpret_cast<u8*>(
120 glMapBufferRange(gl_target, 0, static_cast<GLsizeiptr>(buffer_size),
121 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_FLUSH_EXPLICIT_BIT));
122} 54}
123 55
124void StorageBuffer::Release() { 56std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr alignment) {
125 if (gl_buffer.handle == 0)
126 return;
127
128 glUnmapBuffer(gl_target);
129
130 gl_buffer.Release();
131 head.clear();
132 tail.clear();
133}
134
135std::pair<u8*, GLintptr> StorageBuffer::Map(size_t size, size_t alignment) {
136 ASSERT(size <= buffer_size); 57 ASSERT(size <= buffer_size);
58 ASSERT(alignment <= buffer_size);
59 mapped_size = size;
137 60
138 OGLSync sync; 61 if (alignment > 0) {
139 62 buffer_pos = Common::AlignUp<size_t>(buffer_pos, alignment);
140 buffer_pos = Common::AlignUp(buffer_pos, alignment);
141 size_t effective_offset = Common::AlignDown(buffer_pos, buffer_sync_subdivide);
142
143 if (!head.empty() &&
144 (effective_offset > head.back().offset || buffer_pos + size > buffer_size)) {
145 ASSERT(head.back().sync.handle == 0);
146 head.back().sync.Create();
147 } 63 }
148 64
65 bool invalidate = false;
149 if (buffer_pos + size > buffer_size) { 66 if (buffer_pos + size > buffer_size) {
150 if (!tail.empty()) {
151 std::swap(sync, tail.back().sync);
152 tail.clear();
153 }
154 std::swap(tail, head);
155 buffer_pos = 0; 67 buffer_pos = 0;
156 effective_offset = 0; 68 invalidate = true;
157 }
158 69
159 while (!tail.empty() && buffer_pos + size > tail.front().offset) { 70 if (persistent) {
160 std::swap(sync, tail.front().sync); 71 glUnmapBuffer(gl_target);
161 tail.pop_front(); 72 }
162 } 73 }
163 74
164 if (sync.handle != 0) { 75 if (invalidate | !persistent) {
165 glClientWaitSync(sync.handle, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); 76 GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) |
166 sync.Release(); 77 (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) |
78 (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT);
79 mapped_ptr = static_cast<u8*>(
80 glMapBufferRange(gl_target, buffer_pos, buffer_size - buffer_pos, flags));
81 mapped_offset = buffer_pos;
167 } 82 }
168 83
169 if (head.empty() || effective_offset > head.back().offset) { 84 return std::make_tuple(mapped_ptr + buffer_pos - mapped_offset, buffer_pos, invalidate);
170 head.emplace_back(); 85}
171 head.back().offset = effective_offset; 86
87void OGLStreamBuffer::Unmap(GLsizeiptr size) {
88 ASSERT(size <= mapped_size);
89
90 if (!coherent && size > 0) {
91 glFlushMappedBufferRange(gl_target, buffer_pos - mapped_offset, size);
172 } 92 }
173 93
174 mapped_size = size; 94 if (!persistent) {
175 return std::make_pair(&mapped_ptr[buffer_pos], static_cast<GLintptr>(buffer_pos)); 95 glUnmapBuffer(gl_target);
176} 96 }
177 97
178void StorageBuffer::Unmap() { 98 buffer_pos += size;
179 glFlushMappedBufferRange(gl_target, static_cast<GLintptr>(buffer_pos),
180 static_cast<GLsizeiptr>(mapped_size));
181 buffer_pos += mapped_size;
182} 99}
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index e78dc5784..45592daaf 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -2,35 +2,41 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#include <tuple>
6
7#include <memory>
8#include <glad/glad.h> 6#include <glad/glad.h>
9#include "common/common_types.h" 7#include "common/common_types.h"
10#include "video_core/renderer_opengl/gl_resource_manager.h" 8#include "video_core/renderer_opengl/gl_resource_manager.h"
11 9
12class OGLStreamBuffer : private NonCopyable { 10class OGLStreamBuffer : private NonCopyable {
13public: 11public:
14 explicit OGLStreamBuffer(GLenum target); 12 explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false);
15 virtual ~OGLStreamBuffer() = default; 13 ~OGLStreamBuffer();
16
17public:
18 static std::unique_ptr<OGLStreamBuffer> MakeBuffer(bool storage_buffer, GLenum target);
19
20 virtual void Create(size_t size, size_t sync_subdivide) = 0;
21 virtual void Release() {}
22 14
23 GLuint GetHandle() const; 15 GLuint GetHandle() const;
16 GLsizeiptr GetSize() const;
17
18 /*
19 * Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes
20 * and the optional alignment requirement.
21 * If the buffer is full, the whole buffer is reallocated which invalidates old chunks.
22 * The return values are the pointer to the new chunk, the offset within the buffer,
23 * and the invalidation flag for previous chunks.
24 * The actual used size must be specified on unmapping the chunk.
25 */
26 std::tuple<u8*, GLintptr, bool> Map(GLsizeiptr size, GLintptr alignment = 0);
24 27
25 virtual std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) = 0; 28 void Unmap(GLsizeiptr size);
26 virtual void Unmap() = 0;
27 29
28protected: 30private:
29 OGLBuffer gl_buffer; 31 OGLBuffer gl_buffer;
30 GLenum gl_target; 32 GLenum gl_target;
31 33
32 size_t buffer_pos = 0; 34 bool coherent = false;
33 size_t buffer_size = 0; 35 bool persistent = false;
34 size_t buffer_sync_subdivide = 0; 36
35 size_t mapped_size = 0; 37 GLintptr buffer_pos = 0;
38 GLsizeiptr buffer_size = 0;
39 GLintptr mapped_offset = 0;
40 GLsizeiptr mapped_size = 0;
41 u8* mapped_ptr = nullptr;
36}; 42};