yuzu/src/video_core/renderer_opengl/gl_buffer_cache.h

216 lines
7.5 KiB
C
Raw Normal View History

2022-04-23 22:49:07 +04:00
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2020-12-28 19:15:37 +04:00
#pragma once
#include <array>
2021-01-17 06:19:34 +04:00
#include <span>
2020-12-28 19:15:37 +04:00
#include "common/common_types.h"
#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-07-10 01:54:15 +04:00
[[nodiscard]] GLuint View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
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-07-10 01:54:15 +04:00
struct BufferView {
u32 offset;
u32 size;
VideoCore::Surface::PixelFormat format;
OGLTexture texture;
};
2021-01-17 06:19:34 +04:00
GLuint64EXT address = 0;
OGLBuffer buffer;
GLenum current_residency_access = GL_NONE;
2021-07-10 01:54:15 +04:00
std::vector<BufferView> views;
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);
2021-07-13 06:45:17 +04:00
void ClearBuffer(Buffer& dest_buffer, u32 offset, size_t size, u32 value);
2021-01-17 06:19:34 +04:00
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-07-10 01:54:15 +04:00
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
VideoCore::Surface::PixelFormat format);
void BindImageBuffer(Buffer& buffer, u32 offset, u32 size,
VideoCore::Surface::PixelFormat format);
2022-03-25 10:21:10 +04:00
u64 GetDeviceMemoryUsage() const;
2021-01-17 06:19:34 +04:00
void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) {
2021-07-10 01:54:15 +04:00
const GLuint handle = fast_uniforms[stage][binding_index].handle;
const GLsizeiptr gl_size = static_cast<GLsizeiptr>(size);
2021-01-17 06:19:34 +04:00
if (use_assembly_shaders) {
glBindBufferRangeNV(PABO_LUT[stage], binding_index, handle, 0, gl_size);
} else {
2021-07-10 01:54:15 +04:00
const GLuint base_binding = graphics_base_uniform_bindings[stage];
2021-01-17 06:19:34 +04:00
const GLuint binding = base_binding + binding_index;
2021-07-10 01:54:15 +04:00
glBindBufferRange(GL_UNIFORM_BUFFER, binding, handle, 0, gl_size);
2021-01-17 06:19:34 +04:00
}
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));
2021-07-10 01:54:15 +04:00
const GLuint base_binding = graphics_base_uniform_bindings[stage];
2021-01-17 06:19:34 +04:00
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
2021-07-10 01:54:15 +04:00
[[nodiscard]] bool SupportsNonZeroUniformOffset() const noexcept {
return !use_assembly_shaders;
}
void SetBaseUniformBindings(const std::array<GLuint, 5>& bindings) {
graphics_base_uniform_bindings = bindings;
}
void SetBaseStorageBindings(const std::array<GLuint, 5>& bindings) {
graphics_base_storage_bindings = bindings;
}
void SetImagePointers(GLuint* texture_handles_, GLuint* image_handles_) {
texture_handles = texture_handles_;
image_handles = image_handles_;
}
void SetEnableStorageBuffers(bool use_storage_buffers_) {
use_storage_buffers = use_storage_buffers_;
}
2022-01-16 11:10:16 +04:00
u64 GetDeviceLocalMemory() const {
return device_access_memory;
}
bool CanReportMemoryUsage() const {
2022-03-25 10:21:10 +04:00
return device.CanReportMemoryUsage();
2022-01-16 11:10:16 +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-07-10 01:54:15 +04:00
bool use_storage_buffers = false;
2021-01-19 03:14:45 +04:00
u32 max_attributes = 0;
2021-07-10 01:54:15 +04:00
std::array<GLuint, 5> graphics_base_uniform_bindings{};
std::array<GLuint, 5> graphics_base_storage_bindings{};
GLuint* texture_handles = nullptr;
GLuint* image_handles = nullptr;
2021-01-19 03:14:45 +04:00
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;
2022-01-16 11:10:16 +04:00
u64 device_access_memory;
2021-01-17 06:19:34 +04:00
};
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;
2021-07-10 01:54:15 +04:00
static constexpr bool SEPARATE_IMAGE_BUFFER_BINDINGS = true;
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