// Copyright 2018 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include #include #include "common/assert.h" #include "common/microprofile.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/rasterizer_interface.h" #include "video_core/renderer_opengl/gl_buffer_cache.h" #include "video_core/renderer_opengl/gl_device.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_resource_manager.h" namespace OpenGL { using Maxwell = Tegra::Engines::Maxwell3D::Regs; MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size) : VideoCommon::BufferBlock{cpu_addr, size} { gl_buffer.Create(); glNamedBufferData(gl_buffer.handle, static_cast(size), nullptr, GL_DYNAMIC_DRAW); if (device.HasVertexBufferUnifiedMemory()) { glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); } } Buffer::~Buffer() = default; void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) { glNamedBufferSubData(Handle(), static_cast(offset), static_cast(size), data); } void Buffer::Download(std::size_t offset, std::size_t size, u8* data) { MICROPROFILE_SCOPE(OpenGL_Buffer_Download); const GLsizeiptr gl_size = static_cast(size); const GLintptr gl_offset = static_cast(offset); if (read_buffer.handle == 0) { read_buffer.Create(); glNamedBufferData(read_buffer.handle, static_cast(Size()), nullptr, GL_STREAM_READ); } glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); glCopyNamedBufferSubData(gl_buffer.handle, read_buffer.handle, gl_offset, gl_offset, gl_size); glGetNamedBufferSubData(read_buffer.handle, gl_offset, gl_size, data); } void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, std::size_t size) { glCopyNamedBufferSubData(src.Handle(), Handle(), static_cast(src_offset), static_cast(dst_offset), static_cast(size)); } OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, const Device& device_, std::size_t stream_size) : GenericBufferCache{rasterizer, system, std::make_unique(device_, stream_size, true)}, device{device_} { if (!device.HasFastBufferSubData()) { return; } static constexpr GLsizeiptr size = static_cast(Maxwell::MaxConstBufferSize); glCreateBuffers(static_cast(std::size(cbufs)), std::data(cbufs)); for (const GLuint cbuf : cbufs) { glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW); } } OGLBufferCache::~OGLBufferCache() { glDeleteBuffers(static_cast(std::size(cbufs)), std::data(cbufs)); } std::shared_ptr OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { return std::make_shared(device, cpu_addr, size); } OGLBufferCache::BufferInfo OGLBufferCache::GetEmptyBuffer(std::size_t) { return {0, 0, 0}; } OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, std::size_t size) { DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); const GLuint cbuf = cbufs[cbuf_cursor++]; glNamedBufferSubData(cbuf, 0, static_cast(size), raw_pointer); return {cbuf, 0, 0}; } } // namespace OpenGL