gl_rasterizer: Implement AccelerateDisplay to forward textures to framebuffers.
This commit is contained in:
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
|
/// Attempt to use a faster method to display the framebuffer to screen
|
||||||
virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
|
virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
|
||||||
VAddr framebuffer_addr, u32 pixel_stride,
|
u32 pixel_stride, ScreenInfo& screen_info) {
|
||||||
ScreenInfo& screen_info) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -468,11 +468,30 @@ bool RasterizerOpenGL::AccelerateFill(const void* config) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
|
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
VAddr framebuffer_addr, u32 pixel_stride,
|
VAddr framebuffer_addr, u32 pixel_stride,
|
||||||
ScreenInfo& screen_info) {
|
ScreenInfo& screen_info) {
|
||||||
// TODO(bunnei): ImplementMe
|
if (!framebuffer_addr) {
|
||||||
return false;
|
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() {
|
void RasterizerOpenGL::SamplerInfo::Create() {
|
||||||
|
|
|
@ -436,3 +436,29 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
|
||||||
|
|
||||||
return surface;
|
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) {
|
static SurfaceType GetFormatType(PixelFormat pixel_format) {
|
||||||
if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
|
if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
|
||||||
return SurfaceType::ColorTexture;
|
return SurfaceType::ColorTexture;
|
||||||
|
@ -302,6 +312,7 @@ public:
|
||||||
const MathUtil::Rectangle<s32>& viewport);
|
const MathUtil::Rectangle<s32>& viewport);
|
||||||
void LoadSurface(const Surface& surface);
|
void LoadSurface(const Surface& surface);
|
||||||
void FlushSurface(const Surface& surface);
|
void FlushSurface(const Surface& surface);
|
||||||
|
Surface TryFindFramebufferSurface(VAddr cpu_addr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Surface GetSurface(const SurfaceParams& params);
|
Surface GetSurface(const SurfaceParams& params);
|
||||||
|
|
|
@ -150,7 +150,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
|
||||||
screen_info)) {
|
screen_info)) {
|
||||||
// Reset the screen info's display texture to its own permanent texture
|
// Reset the screen info's display texture to its own permanent texture
|
||||||
screen_info.display_texture = screen_info.texture.resource.handle;
|
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::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes,
|
||||||
Memory::FlushMode::Flush);
|
Memory::FlushMode::Flush);
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct TextureInfo {
|
||||||
/// Structure used for storing information about the display target for the Switch screen
|
/// Structure used for storing information about the display target for the Switch screen
|
||||||
struct ScreenInfo {
|
struct ScreenInfo {
|
||||||
GLuint display_texture;
|
GLuint display_texture;
|
||||||
MathUtil::Rectangle<float> display_texcoords;
|
const MathUtil::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
TextureInfo texture;
|
TextureInfo texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue