yuzu/src/video_core/renderer_opengl/gl_buffer_cache.h

162 lines
5.9 KiB
C
Raw Normal View History

2020-12-28 19:15:37 +04:00
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
2021-01-17 06:19:34 +04:00
#include <span>
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
#include "common/alignment.h"
2020-12-28 19:15:37 +04:00
#include "common/common_types.h"
2021-01-17 06:19:34 +04:00
#include "common/dynamic_library.h"
2020-12-28 19:15:37 +04:00
#include "video_core/buffer_cache/buffer_cache.h"
2021-01-17 06:19:34 +04:00
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_device.h"
2020-12-28 19:15:37 +04:00
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
namespace OpenGL {
2021-01-17 06:19:34 +04:00
class BufferCacheRuntime;
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> {
2020-12-28 19:15:37 +04:00
public:
2021-01-17 06:19:34 +04:00
explicit Buffer(BufferCacheRuntime&, VideoCore::RasterizerInterface& rasterizer, VAddr cpu_addr,
u64 size_bytes);
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams);
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept;
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
void ImmediateDownload(size_t offset, std::span<u8> data) noexcept;
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
void MakeResident(GLenum access) noexcept;
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
[[nodiscard]] GLuint64EXT HostGpuAddr() const noexcept {
return address;
2020-12-28 19:15:37 +04:00
}
2021-01-17 06:19:34 +04:00
[[nodiscard]] GLuint Handle() const noexcept {
return buffer.handle;
2020-12-28 19:15:37 +04:00
}
private:
2021-01-17 06:19:34 +04:00
GLuint64EXT address = 0;
OGLBuffer buffer;
GLenum current_residency_access = GL_NONE;
2020-12-28 19:15:37 +04:00
};
2021-01-17 06:19:34 +04:00
class BufferCacheRuntime {
friend Buffer;
2020-12-28 19:15:37 +04:00
public:
2021-01-17 06:19:34 +04:00
static constexpr u8 INVALID_BINDING = std::numeric_limits<u8>::max();
2021-01-19 03:14:45 +04:00
explicit BufferCacheRuntime(const Device& device_);
2021-01-17 06:19:34 +04:00
void CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
std::span<const VideoCommon::BufferCopy> copies);
void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size);
void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride);
void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size);
void BindComputeUniformBuffer(u32 binding_index, Buffer& buffer, u32 offset, u32 size);
void BindStorageBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size,
bool is_written);
void BindComputeStorageBuffer(u32 binding_index, Buffer& buffer, u32 offset, u32 size,
bool is_written);
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size);
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) {
if (use_assembly_shaders) {
const GLuint handle = fast_uniforms[stage][binding_index].handle;
const GLsizeiptr gl_size = static_cast<GLsizeiptr>(size);
glBindBufferRangeNV(PABO_LUT[stage], binding_index, handle, 0, gl_size);
} else {
const GLuint base_binding = device.GetBaseBindings(stage).uniform_buffer;
const GLuint binding = base_binding + binding_index;
glBindBufferRange(GL_UNIFORM_BUFFER, binding,
fast_uniforms[stage][binding_index].handle, 0,
static_cast<GLsizeiptr>(size));
}
2020-12-28 19:15:37 +04:00
}
2021-01-17 06:19:34 +04:00
void PushFastUniformBuffer(size_t stage, u32 binding_index, std::span<const u8> data) {
if (use_assembly_shaders) {
glProgramBufferParametersIuivNV(
PABO_LUT[stage], binding_index, 0,
static_cast<GLsizei>(data.size_bytes() / sizeof(GLuint)),
reinterpret_cast<const GLuint*>(data.data()));
} else {
glNamedBufferSubData(fast_uniforms[stage][binding_index].handle, 0,
static_cast<GLsizeiptr>(data.size_bytes()), data.data());
}
}
std::span<u8> BindMappedUniformBuffer(size_t stage, u32 binding_index, u32 size) noexcept {
const auto [mapped_span, offset] = stream_buffer->Request(static_cast<size_t>(size));
const GLuint base_binding = device.GetBaseBindings(stage).uniform_buffer;
const GLuint binding = base_binding + binding_index;
glBindBufferRange(GL_UNIFORM_BUFFER, binding, stream_buffer->Handle(),
static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
return mapped_span;
}
2020-12-28 19:15:37 +04:00
2021-01-17 06:19:34 +04:00
[[nodiscard]] const GLvoid* IndexOffset() const noexcept {
return reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(index_buffer_offset));
}
[[nodiscard]] bool HasFastBufferSubData() const noexcept {
2021-01-19 03:14:45 +04:00
return has_fast_buffer_sub_data;
2021-01-17 06:19:34 +04:00
}
2020-12-28 19:15:37 +04:00
private:
2021-01-17 06:19:34 +04:00
static constexpr std::array PABO_LUT{
GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV,
GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV, GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV,
GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV,
};
2020-12-28 19:15:37 +04:00
const Device& device;
2021-01-19 03:14:45 +04:00
bool has_fast_buffer_sub_data = false;
2021-01-17 06:19:34 +04:00
bool use_assembly_shaders = false;
bool has_unified_vertex_buffers = false;
2021-01-19 03:14:45 +04:00
u32 max_attributes = 0;
std::optional<StreamBuffer> stream_buffer;
2021-01-17 06:19:34 +04:00
std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>,
VideoCommon::NUM_STAGES>
fast_uniforms;
2021-01-19 03:14:45 +04:00
std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>,
VideoCommon::NUM_STAGES>
copy_uniforms;
std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms;
2021-01-17 06:19:34 +04:00
u32 index_buffer_offset = 0;
};
struct BufferCacheParams {
using Runtime = OpenGL::BufferCacheRuntime;
using Buffer = OpenGL::Buffer;
static constexpr bool IS_OPENGL = true;
static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = true;
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true;
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true;
static constexpr bool NEEDS_BIND_STORAGE_INDEX = true;
static constexpr bool USE_MEMORY_MAPS = false;
2020-12-28 19:15:37 +04:00
};
2021-01-17 06:19:34 +04:00
using BufferCache = VideoCommon::BufferCache<BufferCacheParams>;
2020-12-28 19:15:37 +04:00
} // namespace OpenGL