2018-08-29 00:27:03 +02:00
|
|
|
// Copyright 2018 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2019-11-02 08:08:31 +01:00
|
|
|
#include <array>
|
2021-01-17 00:48:58 +01:00
|
|
|
#include <span>
|
2018-08-29 00:27:03 +02:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
#include "common/alignment.h"
|
2018-08-29 00:27:03 +02:00
|
|
|
#include "common/common_types.h"
|
2021-01-17 00:48:58 +01:00
|
|
|
#include "common/dynamic_library.h"
|
2019-07-19 16:50:40 +02:00
|
|
|
#include "video_core/buffer_cache/buffer_cache.h"
|
2021-01-17 00:48:58 +01:00
|
|
|
#include "video_core/rasterizer_interface.h"
|
|
|
|
#include "video_core/renderer_opengl/gl_device.h"
|
2018-08-29 00:27:03 +02:00
|
|
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
|
|
|
#include "video_core/renderer_opengl/gl_stream_buffer.h"
|
2019-06-15 00:58:16 +02:00
|
|
|
|
2018-08-29 00:27:03 +02:00
|
|
|
namespace OpenGL {
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
class BufferCacheRuntime;
|
2018-11-08 12:08:00 +01:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> {
|
2019-07-19 16:50:40 +02:00
|
|
|
public:
|
2021-01-17 00:48:58 +01:00
|
|
|
explicit Buffer(BufferCacheRuntime&, VideoCore::RasterizerInterface& rasterizer, VAddr cpu_addr,
|
|
|
|
u64 size_bytes);
|
|
|
|
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams);
|
2019-07-19 16:50:40 +02:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept;
|
2020-06-20 01:47:48 +02:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
void ImmediateDownload(size_t offset, std::span<u8> data) noexcept;
|
2020-06-20 01:47:48 +02:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
void MakeResident(GLenum access) noexcept;
|
2020-06-20 01:47:48 +02:00
|
|
|
|
2021-05-23 09:28:34 +02:00
|
|
|
[[nodiscard]] GLuint View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
[[nodiscard]] GLuint64EXT HostGpuAddr() const noexcept {
|
|
|
|
return address;
|
2019-07-19 16:50:40 +02:00
|
|
|
}
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
[[nodiscard]] GLuint Handle() const noexcept {
|
|
|
|
return buffer.handle;
|
2020-05-11 21:35:04 +02:00
|
|
|
}
|
|
|
|
|
2019-07-19 16:50:40 +02:00
|
|
|
private:
|
2021-05-23 09:28:34 +02:00
|
|
|
struct BufferView {
|
|
|
|
u32 offset;
|
|
|
|
u32 size;
|
|
|
|
VideoCore::Surface::PixelFormat format;
|
|
|
|
OGLTexture texture;
|
|
|
|
};
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
GLuint64EXT address = 0;
|
|
|
|
OGLBuffer buffer;
|
|
|
|
GLenum current_residency_access = GL_NONE;
|
2021-05-23 09:28:34 +02:00
|
|
|
std::vector<BufferView> views;
|
2019-07-19 16:50:40 +02:00
|
|
|
};
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
class BufferCacheRuntime {
|
|
|
|
friend Buffer;
|
|
|
|
|
2019-02-19 02:58:32 +01:00
|
|
|
public:
|
2021-01-17 00:48:58 +01:00
|
|
|
static constexpr u8 INVALID_BINDING = std::numeric_limits<u8>::max();
|
|
|
|
|
2021-01-18 23:04:27 +01:00
|
|
|
explicit BufferCacheRuntime(const Device& device_);
|
2021-01-17 00:48:58 +01:00
|
|
|
|
|
|
|
void CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
|
|
|
|
std::span<const VideoCommon::BufferCopy> copies);
|
|
|
|
|
2021-07-13 03:33:08 +02:00
|
|
|
void ClearBuffer(Buffer& dest_buffer, u32 offset, size_t size, u32 value);
|
|
|
|
|
2021-01-17 00:48:58 +01: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);
|
2019-05-28 01:50:11 +02:00
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size);
|
2019-07-06 04:49:45 +02:00
|
|
|
|
2021-05-23 09:28:34 +02: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);
|
|
|
|
|
2021-01-17 00:48:58 +01: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 {
|
2021-05-23 09:28:34 +02:00
|
|
|
const GLuint base_binding = graphics_base_uniform_bindings[stage];
|
2021-01-17 00:48:58 +01:00
|
|
|
const GLuint binding = base_binding + binding_index;
|
|
|
|
glBindBufferRange(GL_UNIFORM_BUFFER, binding,
|
|
|
|
fast_uniforms[stage][binding_index].handle, 0,
|
|
|
|
static_cast<GLsizeiptr>(size));
|
|
|
|
}
|
2019-11-02 08:08:31 +01:00
|
|
|
}
|
|
|
|
|
2021-01-17 00:48:58 +01: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-05-23 09:28:34 +02:00
|
|
|
const GLuint base_binding = graphics_base_uniform_bindings[stage];
|
2021-01-17 00:48:58 +01: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;
|
|
|
|
}
|
2019-05-28 01:50:11 +02:00
|
|
|
|
2021-01-17 00:48:58 +01: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-18 23:00:00 +01:00
|
|
|
return has_fast_buffer_sub_data;
|
2021-01-17 00:48:58 +01:00
|
|
|
}
|
2019-11-02 08:08:31 +01:00
|
|
|
|
2021-05-23 09:28:34 +02:00
|
|
|
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_;
|
|
|
|
}
|
|
|
|
|
2021-05-26 23:32:59 +02:00
|
|
|
void SetEnableStorageBuffers(bool use_storage_buffers_) {
|
|
|
|
use_storage_buffers = use_storage_buffers_;
|
|
|
|
}
|
|
|
|
|
2019-11-02 08:08:31 +01:00
|
|
|
private:
|
2021-01-17 00:48:58 +01: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-05-11 21:35:04 +02:00
|
|
|
|
|
|
|
const Device& device;
|
|
|
|
|
2021-01-18 23:00:00 +01:00
|
|
|
bool has_fast_buffer_sub_data = false;
|
2021-01-17 00:48:58 +01:00
|
|
|
bool use_assembly_shaders = false;
|
|
|
|
bool has_unified_vertex_buffers = false;
|
|
|
|
|
2021-05-26 23:32:59 +02:00
|
|
|
bool use_storage_buffers = false;
|
|
|
|
|
2021-01-18 23:00:00 +01:00
|
|
|
u32 max_attributes = 0;
|
|
|
|
|
2021-05-23 09:28:34 +02: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-18 23:00:00 +01:00
|
|
|
std::optional<StreamBuffer> stream_buffer;
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>,
|
|
|
|
VideoCommon::NUM_STAGES>
|
|
|
|
fast_uniforms;
|
2021-01-18 23:00:00 +01: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 00:48:58 +01: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;
|
2021-05-23 09:28:34 +02:00
|
|
|
static constexpr bool SEPARATE_IMAGE_BUFFER_BINDINGS = true;
|
2018-08-29 00:27:03 +02:00
|
|
|
};
|
|
|
|
|
2021-01-17 00:48:58 +01:00
|
|
|
using BufferCache = VideoCommon::BufferCache<BufferCacheParams>;
|
|
|
|
|
2018-08-29 00:27:03 +02:00
|
|
|
} // namespace OpenGL
|