gl_rasterizer: Implement AccelerateDisplay to forward textures to framebuffers.

master
bunnei 2018-06-24 17:42:29 +07:00
parent ff6785f3e8
commit 3f9f047375
6 changed files with 62 additions and 8 deletions

@ -51,9 +51,8 @@ public:
}
/// Attempt to use a faster method to display the framebuffer to screen
virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
VAddr framebuffer_addr, u32 pixel_stride,
ScreenInfo& screen_info) {
virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride, ScreenInfo& screen_info) {
return false;
}

@ -468,11 +468,30 @@ bool RasterizerOpenGL::AccelerateFill(const void* config) {
return true;
}
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride,
ScreenInfo& screen_info) {
// TODO(bunnei): ImplementMe
return false;
if (!framebuffer_addr) {
return {};
}
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
const auto& surface{res_cache.TryFindFramebufferSurface(framebuffer_addr)};
if (!surface) {
return {};
}
// Verify that the cached surface is the same size and format as the requested framebuffer
const auto& params{surface->GetSurfaceParams()};
const auto& pixel_format{SurfaceParams::PixelFormatFromGPUPixelFormat(config.pixel_format)};
ASSERT_MSG(params.width == config.width, "Framebuffer width is different");
ASSERT_MSG(params.height == config.height, "Framebuffer height is different");
ASSERT_MSG(params.pixel_format == pixel_format, "Framebuffer pixel_format is different");
screen_info.display_texture = surface->Texture().handle;
return true;
}
void RasterizerOpenGL::SamplerInfo::Create() {

@ -436,3 +436,29 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
return surface;
}
Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const {
// Tries to find the GPU address of a framebuffer based on the CPU address. This is because
// final output framebuffers are specified by CPU address, but internally our GPU cache uses GPU
// addresses. We iterate through all cached framebuffers, and compare their starting CPU address
// to the one provided. This is obviously not great, and won't work if the framebuffer overlaps
// surfaces.
std::vector<Surface> surfaces;
for (const auto& surface : surface_cache) {
const auto& params = surface.second->GetSurfaceParams();
const VAddr surface_cpu_addr = params.GetCpuAddr();
if (cpu_addr >= surface_cpu_addr && cpu_addr < (surface_cpu_addr + params.size_in_bytes)) {
ASSERT_MSG(cpu_addr == surface_cpu_addr, "overlapping surfaces are unsupported");
surfaces.push_back(surface.second);
}
}
if (surfaces.empty()) {
return {};
}
ASSERT_MSG(surfaces.size() == 1, ">1 surface is unsupported");
return surfaces[0];
}

@ -220,6 +220,16 @@ struct SurfaceParams {
}
}
static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
switch (format) {
case Tegra::FramebufferConfig::PixelFormat::ABGR8:
return PixelFormat::ABGR8;
default:
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();
}
}
static SurfaceType GetFormatType(PixelFormat pixel_format) {
if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
return SurfaceType::ColorTexture;
@ -302,6 +312,7 @@ public:
const MathUtil::Rectangle<s32>& viewport);
void LoadSurface(const Surface& surface);
void FlushSurface(const Surface& surface);
Surface TryFindFramebufferSurface(VAddr cpu_addr) const;
private:
Surface GetSurface(const SurfaceParams& params);

@ -150,7 +150,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
screen_info)) {
// Reset the screen info's display texture to its own permanent texture
screen_info.display_texture = screen_info.texture.resource.handle;
screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
Memory::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes,
Memory::FlushMode::Flush);

@ -27,7 +27,7 @@ struct TextureInfo {
/// Structure used for storing information about the display target for the Switch screen
struct ScreenInfo {
GLuint display_texture;
MathUtil::Rectangle<float> display_texcoords;
const MathUtil::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
TextureInfo texture;
};