Batch flushing buffer.

This commit is contained in:
Ben Vanik 2015-01-02 18:01:48 -08:00
parent bb15d2f62f
commit 5236477043
4 changed files with 36 additions and 5 deletions

View File

@ -24,6 +24,8 @@ CircularBuffer::CircularBuffer(size_t capacity, size_t alignment)
: capacity_(capacity), : capacity_(capacity),
alignment_(alignment), alignment_(alignment),
write_head_(0), write_head_(0),
dirty_start_(UINT64_MAX),
dirty_end_(0),
buffer_(0), buffer_(0),
gpu_base_(0), gpu_base_(0),
host_base_(nullptr) {} host_base_(nullptr) {}
@ -63,12 +65,15 @@ void CircularBuffer::Shutdown() {
buffer_ = 0; buffer_ = 0;
} }
bool CircularBuffer::CanAcquire(size_t length) {
size_t aligned_length = poly::round_up(length, alignment_);
return write_head_ + aligned_length <= capacity_;
}
CircularBuffer::Allocation CircularBuffer::Acquire(size_t length) { CircularBuffer::Allocation CircularBuffer::Acquire(size_t length) {
// Addresses must always be % 256. // Addresses must always be % 256.
size_t aligned_length = poly::round_up(length, alignment_); size_t aligned_length = poly::round_up(length, alignment_);
assert_true(aligned_length <= capacity_, "Request too large"); assert_true(aligned_length <= capacity_, "Request too large");
if (write_head_ + aligned_length > capacity_) { if (write_head_ + aligned_length > capacity_) {
// Flush and wait. // Flush and wait.
WaitUntilClean(); WaitUntilClean();
@ -79,16 +84,30 @@ CircularBuffer::Allocation CircularBuffer::Acquire(size_t length) {
allocation.gpu_ptr = gpu_base_ + write_head_; allocation.gpu_ptr = gpu_base_ + write_head_;
allocation.offset = write_head_; allocation.offset = write_head_;
allocation.length = length; allocation.length = length;
allocation.aligned_length = aligned_length;
write_head_ += aligned_length; write_head_ += aligned_length;
return allocation; return allocation;
} }
void CircularBuffer::Commit(Allocation allocation) { void CircularBuffer::Commit(Allocation allocation) {
glFlushMappedNamedBufferRange(buffer_, allocation.gpu_ptr - gpu_base_, uintptr_t start = allocation.gpu_ptr - gpu_base_;
allocation.length); uintptr_t end = start + allocation.aligned_length;
dirty_start_ = std::min(dirty_start_, start);
dirty_end_ = std::max(dirty_end_, end);
}
void CircularBuffer::Flush() {
if (dirty_start_ == dirty_end_ || dirty_start_ == UINT64_MAX) {
return;
}
glFlushMappedNamedBufferRange(buffer_, dirty_start_,
dirty_end_ - dirty_start_);
dirty_start_ = UINT64_MAX;
dirty_end_ = 0;
} }
void CircularBuffer::WaitUntilClean() { void CircularBuffer::WaitUntilClean() {
Flush();
glFinish(); glFinish();
write_head_ = 0; write_head_ = 0;
} }

View File

@ -28,6 +28,7 @@ class CircularBuffer {
GLuint64 gpu_ptr; GLuint64 gpu_ptr;
size_t offset; size_t offset;
size_t length; size_t length;
size_t aligned_length;
}; };
bool Initialize(); bool Initialize();
@ -35,8 +36,10 @@ class CircularBuffer {
GLuint handle() const { return buffer_; } GLuint handle() const { return buffer_; }
bool CanAcquire(size_t length);
Allocation Acquire(size_t length); Allocation Acquire(size_t length);
void Commit(Allocation allocation); void Commit(Allocation allocation);
void Flush();
void WaitUntilClean(); void WaitUntilClean();
@ -44,6 +47,8 @@ class CircularBuffer {
size_t capacity_; size_t capacity_;
size_t alignment_; size_t alignment_;
uintptr_t write_head_; uintptr_t write_head_;
uintptr_t dirty_start_;
uintptr_t dirty_end_;
GLuint buffer_; GLuint buffer_;
GLuint64 gpu_base_; GLuint64 gpu_base_;
uint8_t* host_base_; uint8_t* host_base_;

View File

@ -1428,6 +1428,7 @@ bool CommandProcessor::IssueDraw(DrawCommand* draw_command) {
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, scratch_buffer_.handle(), glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, scratch_buffer_.handle(),
allocation.offset, allocation.length); allocation.offset, allocation.length);
scratch_buffer_.Commit(std::move(allocation)); scratch_buffer_.Commit(std::move(allocation));
scratch_buffer_.Flush();
if (cmd.index_buffer.address) { if (cmd.index_buffer.address) {
// Indexed draw. // Indexed draw.

View File

@ -382,7 +382,11 @@ GL4ProfilerDisplay::Vertex* GL4ProfilerDisplay::BeginVertices(size_t count) {
if (draw_command_count_ + 1 > kMaxCommands) { if (draw_command_count_ + 1 > kMaxCommands) {
Flush(); Flush();
} }
current_allocation_ = vertex_buffer_.Acquire(sizeof(Vertex) * count); size_t total_length = sizeof(Vertex) * count;
if (!vertex_buffer_.CanAcquire(total_length)) {
Flush();
}
current_allocation_ = vertex_buffer_.Acquire(total_length);
return reinterpret_cast<Vertex*>(current_allocation_.host_ptr); return reinterpret_cast<Vertex*>(current_allocation_.host_ptr);
} }
@ -408,12 +412,14 @@ void GL4ProfilerDisplay::Flush() {
if (!draw_command_count_) { if (!draw_command_count_) {
return; return;
} }
vertex_buffer_.Flush();
for (size_t i = 0; i < draw_command_count_; ++i) { for (size_t i = 0; i < draw_command_count_; ++i) {
glDrawArrays(draw_commands_[i].prim_type, glDrawArrays(draw_commands_[i].prim_type,
GLint(draw_commands_[i].vertex_offset), GLint(draw_commands_[i].vertex_offset),
GLsizei(draw_commands_[i].vertex_count)); GLsizei(draw_commands_[i].vertex_count));
} }
draw_command_count_ = 0; draw_command_count_ = 0;
// TODO(benvanik): don't finish here.
vertex_buffer_.WaitUntilClean(); vertex_buffer_.WaitUntilClean();
} }