mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 13:31:27 +12:00
gl: Implement basic DMA layer using AMD_pinned_memory
This commit is contained in:
parent
3e516df214
commit
7fdfbe3c52
8 changed files with 177 additions and 3 deletions
120
rpcs3/Emu/RSX/GL/GLDMA.cpp
Normal file
120
rpcs3/Emu/RSX/GL/GLDMA.cpp
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "GLDMA.h"
|
||||||
|
|
||||||
|
#include "Emu/Memory/vm.h"
|
||||||
|
|
||||||
|
namespace gl
|
||||||
|
{
|
||||||
|
static constexpr u32 s_dma_block_size = 0x10000;
|
||||||
|
std::unordered_map<u32, std::unique_ptr<dma_block>> g_dma_pool;
|
||||||
|
|
||||||
|
void dma_block::allocate(u32 base_address, u32 block_size)
|
||||||
|
{
|
||||||
|
// Since this is a userptr block, we don't need to move data around on resize. Just "claim" a different chunk and move on.
|
||||||
|
if (m_data)
|
||||||
|
{
|
||||||
|
m_data->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* userptr = vm::get_super_ptr(base_address);
|
||||||
|
|
||||||
|
m_data = std::make_unique<gl::buffer>();
|
||||||
|
m_data->create(buffer::target::userptr, block_size, userptr);
|
||||||
|
m_base_address = base_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* dma_block::map(const utils::address_range& range) const
|
||||||
|
{
|
||||||
|
ensure(range.inside(this->range()));
|
||||||
|
return vm::get_super_ptr(range.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dma_block::resize(u32 new_length)
|
||||||
|
{
|
||||||
|
if (new_length < length())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocate(m_base_address, new_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dma_block::set_parent(const dma_block* other)
|
||||||
|
{
|
||||||
|
ensure(this->range().inside(other->range()));
|
||||||
|
ensure(other != this);
|
||||||
|
|
||||||
|
m_parent = other;
|
||||||
|
if (m_data)
|
||||||
|
{
|
||||||
|
m_data->remove();
|
||||||
|
m_data.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dma_block::can_map(const utils::address_range& range) const
|
||||||
|
{
|
||||||
|
if (m_parent)
|
||||||
|
{
|
||||||
|
return m_parent->can_map(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
return range.inside(this->range());
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_dma_resources()
|
||||||
|
{
|
||||||
|
g_dma_pool.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::address_range to_dma_block_range(u32 start, u32 length)
|
||||||
|
{
|
||||||
|
const auto start_block_address = start & ~s_dma_block_size;
|
||||||
|
const auto end_block_address = (start + length - 1) & ~s_dma_block_size;
|
||||||
|
return utils::address_range::start_end(start_block_address, end_block_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dma_block& get_block(u32 start, u32 length)
|
||||||
|
{
|
||||||
|
const auto block_range = to_dma_block_range(start, length);
|
||||||
|
auto& block = g_dma_pool[block_range.start];
|
||||||
|
if (!block)
|
||||||
|
{
|
||||||
|
block = std::make_unique<dma_block>();
|
||||||
|
block->allocate(block_range.start, length);
|
||||||
|
return *block;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto range = utils::address_range::start_length(start, length);
|
||||||
|
if (block->can_map(range)) [[ likely ]]
|
||||||
|
{
|
||||||
|
return *block;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto owner = block->head();
|
||||||
|
const auto new_length = (block_range.end + 1) - owner->base_addr();
|
||||||
|
const auto search_end = (block_range.end + 1);
|
||||||
|
|
||||||
|
// 1. Resize to new length
|
||||||
|
auto new_owner = std::make_unique<dma_block>();
|
||||||
|
new_owner->allocate(owner->base_addr(), new_length);
|
||||||
|
|
||||||
|
// 2. Acquire all the extras
|
||||||
|
for (u32 id = owner->base_addr() + s_dma_block_size;
|
||||||
|
id < search_end;
|
||||||
|
id += s_dma_block_size)
|
||||||
|
{
|
||||||
|
ensure((id % s_dma_block_size) == 0);
|
||||||
|
g_dma_pool[id]->set_parent(new_owner.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
block = std::move(new_owner);
|
||||||
|
return *block;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_mapping_handle map_dma(u32 guest_address, u32 length)
|
||||||
|
{
|
||||||
|
auto& block = get_block(guest_address, length);
|
||||||
|
return { guest_address - block.base_addr(), block.get() };
|
||||||
|
}
|
||||||
|
}
|
41
rpcs3/Emu/RSX/GL/GLDMA.h
Normal file
41
rpcs3/Emu/RSX/GL/GLDMA.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <util/types.hpp>
|
||||||
|
#include "Utilities/address_range.h"
|
||||||
|
|
||||||
|
#include "glutils/buffer_object.h"
|
||||||
|
|
||||||
|
// TODO: Unify the DMA implementation across backends as part of RSX restructuring.
|
||||||
|
namespace gl
|
||||||
|
{
|
||||||
|
using dma_mapping_handle = std::pair<u32, gl::buffer*>;
|
||||||
|
|
||||||
|
dma_mapping_handle map_dma(u32 guest_addr, u32 length);
|
||||||
|
void clear_dma_resources();
|
||||||
|
|
||||||
|
// GL does not currently support mixed block types...
|
||||||
|
class dma_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
dma_block() = default;
|
||||||
|
|
||||||
|
void allocate(u32 base_address, u32 block_size);
|
||||||
|
void resize(u32 new_length);
|
||||||
|
void* map(const utils::address_range& range) const;
|
||||||
|
|
||||||
|
void set_parent(const dma_block* other);
|
||||||
|
const dma_block* head() const { return m_parent; }
|
||||||
|
bool can_map(const utils::address_range& range) const;
|
||||||
|
|
||||||
|
u32 base_addr() const { return m_base_address; }
|
||||||
|
u32 length() const { return m_data ? static_cast<u32>(m_data->size()) : 0; }
|
||||||
|
bool empty() const { return length() == 0; }
|
||||||
|
buffer* get() const { return m_data.get(); }
|
||||||
|
utils::address_range range() const { return utils::address_range::start_length(m_base_address, length()); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_base_address = 0;
|
||||||
|
const dma_block* m_parent = nullptr;
|
||||||
|
std::unique_ptr<gl::buffer> m_data;
|
||||||
|
};
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ namespace gl
|
||||||
void buffer::allocate(GLsizeiptr size, const void* data_, memory_type type, GLenum usage)
|
void buffer::allocate(GLsizeiptr size, const void* data_, memory_type type, GLenum usage)
|
||||||
{
|
{
|
||||||
if (const auto& caps = get_driver_caps();
|
if (const auto& caps = get_driver_caps();
|
||||||
caps.ARB_buffer_storage_supported)
|
m_target != target::userptr && caps.ARB_buffer_storage_supported)
|
||||||
{
|
{
|
||||||
GLenum flags = 0;
|
GLenum flags = 0;
|
||||||
if (type == memory_type::host_visible)
|
if (type == memory_type::host_visible)
|
||||||
|
|
|
@ -15,7 +15,8 @@ namespace gl
|
||||||
element_array = GL_ELEMENT_ARRAY_BUFFER,
|
element_array = GL_ELEMENT_ARRAY_BUFFER,
|
||||||
uniform = GL_UNIFORM_BUFFER,
|
uniform = GL_UNIFORM_BUFFER,
|
||||||
texture = GL_TEXTURE_BUFFER,
|
texture = GL_TEXTURE_BUFFER,
|
||||||
ssbo = GL_SHADER_STORAGE_BUFFER
|
ssbo = GL_SHADER_STORAGE_BUFFER,
|
||||||
|
userptr = GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class access
|
enum class access
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace gl
|
||||||
|
|
||||||
void capabilities::initialize()
|
void capabilities::initialize()
|
||||||
{
|
{
|
||||||
int find_count = 16;
|
int find_count = 17;
|
||||||
int ext_count = 0;
|
int ext_count = 0;
|
||||||
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
|
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
|
||||||
|
|
||||||
|
@ -164,6 +164,13 @@ namespace gl
|
||||||
find_count--;
|
find_count--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check(ext_name, "GL_AMD_pinned_memory"))
|
||||||
|
{
|
||||||
|
AMD_pinned_memory = true;
|
||||||
|
find_count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set GLSL version
|
// Set GLSL version
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace gl
|
||||||
|
|
||||||
bool EXT_dsa_supported = false;
|
bool EXT_dsa_supported = false;
|
||||||
bool EXT_depth_bounds_test = false;
|
bool EXT_depth_bounds_test = false;
|
||||||
|
bool AMD_pinned_memory = false;
|
||||||
bool ARB_dsa_supported = false;
|
bool ARB_dsa_supported = false;
|
||||||
bool ARB_bindless_texture_supported = false;
|
bool ARB_bindless_texture_supported = false;
|
||||||
bool ARB_buffer_storage_supported = false;
|
bool ARB_buffer_storage_supported = false;
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Emu\RSX\GL\GLCompute.h" />
|
<ClInclude Include="Emu\RSX\GL\GLCompute.h" />
|
||||||
|
<ClInclude Include="Emu\RSX\GL\GLDMA.h" />
|
||||||
<ClInclude Include="Emu\RSX\GL\GLOverlays.h" />
|
<ClInclude Include="Emu\RSX\GL\GLOverlays.h" />
|
||||||
<ClInclude Include="Emu\RSX\GL\GLPipelineCompiler.h" />
|
<ClInclude Include="Emu\RSX\GL\GLPipelineCompiler.h" />
|
||||||
<ClInclude Include="Emu\RSX\GL\GLCommonDecompiler.h" />
|
<ClInclude Include="Emu\RSX\GL\GLCommonDecompiler.h" />
|
||||||
|
@ -88,6 +89,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Emu\RSX\GL\GLCommonDecompiler.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLCommonDecompiler.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLCompute.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLCompute.cpp" />
|
||||||
|
<ClCompile Include="Emu\RSX\GL\GLDMA.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLDraw.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLDraw.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLFragmentProgram.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLFragmentProgram.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLGSRender.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLGSRender.cpp" />
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
<ClCompile Include="Emu\RSX\GL\upscalers\fsr1\fsr_pass.cpp">
|
<ClCompile Include="Emu\RSX\GL\upscalers\fsr1\fsr_pass.cpp">
|
||||||
<Filter>upscalers\fsr1</Filter>
|
<Filter>upscalers\fsr1</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\RSX\GL\GLDMA.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Emu\RSX\GL\GLTexture.h" />
|
<ClInclude Include="Emu\RSX\GL\GLTexture.h" />
|
||||||
|
@ -118,6 +119,7 @@
|
||||||
<ClInclude Include="Emu\RSX\GL\upscalers\fsr_pass.h">
|
<ClInclude Include="Emu\RSX\GL\upscalers\fsr_pass.h">
|
||||||
<Filter>upscalers</Filter>
|
<Filter>upscalers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\GL\GLDMA.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="glutils">
|
<Filter Include="glutils">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue