3
0
Fork 0
forked from suyu/suyu

gl_rasterizer: Use DSA for textures

This commit is contained in:
ReinUsesLisp 2019-01-06 18:49:23 -03:00
parent 92b18345a8
commit 4b676e7786
5 changed files with 104 additions and 184 deletions

View file

@ -18,7 +18,6 @@
#include "video_core/morton.h" #include "video_core/morton.h"
#include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/utils.h" #include "video_core/renderer_opengl/utils.h"
#include "video_core/surface.h" #include "video_core/surface.h"
#include "video_core/textures/astc.h" #include "video_core/textures/astc.h"
@ -44,14 +43,14 @@ struct FormatTuple {
bool compressed; bool compressed;
}; };
static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { static void ApplyTextureDefaults(GLuint texture, u32 max_mip_level) {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1);
if (max_mip_level == 1) { if (max_mip_level == 1) {
glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0);
} }
} }
@ -529,55 +528,41 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
CachedSurface::CachedSurface(const SurfaceParams& params) CachedSurface::CachedSurface(const SurfaceParams& params)
: params(params), gl_target(SurfaceTargetToGL(params.target)), : params(params), gl_target(SurfaceTargetToGL(params.target)),
cached_size_in_bytes(params.size_in_bytes) { cached_size_in_bytes(params.size_in_bytes) {
texture.Create(); texture.Create(gl_target);
const auto& rect{params.GetRect()};
// Keep track of previous texture bindings // TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0)
OpenGLState cur_state = OpenGLState::GetCurState(); // alternatives. This signals a bug on those functions.
const auto& old_tex = cur_state.texture_units[0]; const auto width = static_cast<GLsizei>(params.MipWidth(0));
SCOPE_EXIT({ const auto height = static_cast<GLsizei>(params.MipHeight(0));
cur_state.texture_units[0] = old_tex;
cur_state.Apply();
});
cur_state.texture_units[0].texture = texture.handle;
cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
cur_state.Apply();
glActiveTexture(GL_TEXTURE0);
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
gl_internal_format = format_tuple.internal_format; gl_internal_format = format_tuple.internal_format;
gl_is_compressed = format_tuple.compressed;
if (!format_tuple.compressed) { switch (params.target) {
// Only pre-create the texture for non-compressed textures. case SurfaceTarget::Texture1D:
switch (params.target) { glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format,
case SurfaceTarget::Texture1D: width);
glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, break;
format_tuple.internal_format, rect.GetWidth()); case SurfaceTarget::Texture2D:
break; case SurfaceTarget::TextureCubemap:
case SurfaceTarget::Texture2D: glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format,
case SurfaceTarget::TextureCubemap: width, height);
glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, break;
format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); case SurfaceTarget::Texture3D:
break; case SurfaceTarget::Texture2DArray:
case SurfaceTarget::Texture3D: case SurfaceTarget::TextureCubeArray:
case SurfaceTarget::Texture2DArray: glTextureStorage3D(texture.handle, params.max_mip_level, format_tuple.internal_format,
case SurfaceTarget::TextureCubeArray: width, height, params.depth);
glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, break;
format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), default:
params.depth); LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
break; static_cast<u32>(params.target));
default: UNREACHABLE();
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format,
static_cast<u32>(params.target)); width, height);
UNREACHABLE();
glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format,
rect.GetWidth(), rect.GetHeight());
}
} }
ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); ApplyTextureDefaults(texture.handle, params.max_mip_level);
OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString());
@ -752,63 +737,50 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
const auto& rect{params.GetRect(mip_map)}; const auto& rect{params.GetRect(mip_map)};
// Load data from memory to the surface // Load data from memory to the surface
const GLint x0 = static_cast<GLint>(rect.left); const auto x0 = static_cast<GLint>(rect.left);
const GLint y0 = static_cast<GLint>(rect.bottom); const auto y0 = static_cast<GLint>(rect.bottom);
std::size_t buffer_offset = auto buffer_offset =
static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) +
static_cast<std::size_t>(x0)) * static_cast<std::size_t>(x0)) *
GetBytesPerPixel(params.pixel_format); GetBytesPerPixel(params.pixel_format);
const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
const GLuint target_tex = texture.handle;
OpenGLState cur_state = OpenGLState::GetCurState();
const auto& old_tex = cur_state.texture_units[0];
SCOPE_EXIT({
cur_state.texture_units[0] = old_tex;
cur_state.Apply();
});
cur_state.texture_units[0].texture = target_tex;
cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
cur_state.Apply();
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0); ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map))); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map)));
GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); const auto image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false));
glActiveTexture(GL_TEXTURE0);
if (tuple.compressed) { if (tuple.compressed) {
switch (params.target) { switch (params.target) {
case SurfaceTarget::Texture2D: case SurfaceTarget::Texture2D:
glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, glCompressedTextureSubImage2D(
static_cast<GLsizei>(params.MipWidth(mip_map)), texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, image_size,
&gl_buffer[mip_map][buffer_offset]); &gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::Texture3D: case SurfaceTarget::Texture3D:
glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, glCompressedTextureSubImage3D(
static_cast<GLsizei>(params.MipWidth(mip_map)), texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.MipHeight(mip_map)),
static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, static_cast<GLsizei>(params.MipDepth(mip_map)), tuple.internal_format, image_size,
&gl_buffer[mip_map][buffer_offset]); &gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::Texture2DArray: case SurfaceTarget::Texture2DArray:
case SurfaceTarget::TextureCubeArray: case SurfaceTarget::TextureCubeArray:
glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, glCompressedTextureSubImage3D(
static_cast<GLsizei>(params.MipWidth(mip_map)), texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.depth),
static_cast<GLsizei>(params.depth), 0, image_size, tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]);
&gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::TextureCubemap: { case SurfaceTarget::TextureCubemap: {
GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); const auto layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map));
for (std::size_t face = 0; face < params.depth; ++face) { for (std::size_t face = 0; face < params.depth; ++face) {
glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), glCompressedTextureSubImage3D(
mip_map, tuple.internal_format, texture.handle, mip_map, 0, 0, static_cast<GLint>(face),
static_cast<GLsizei>(params.MipWidth(mip_map)), static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)), 0, static_cast<GLsizei>(params.MipHeight(mip_map)), 1, tuple.internal_format,
layer_size, &gl_buffer[mip_map][buffer_offset]); layer_size, &gl_buffer[mip_map][buffer_offset]);
buffer_offset += layer_size; buffer_offset += layer_size;
} }
break; break;
@ -817,46 +789,43 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
static_cast<u32>(params.target)); static_cast<u32>(params.target));
UNREACHABLE(); UNREACHABLE();
glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, glCompressedTextureSubImage2D(
static_cast<GLsizei>(params.MipWidth(mip_map)), texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)), 0, static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format,
static_cast<GLsizei>(params.size_in_bytes_gl), static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[mip_map][buffer_offset]);
&gl_buffer[mip_map][buffer_offset]);
} }
} else { } else {
switch (params.target) { switch (params.target) {
case SurfaceTarget::Texture1D: case SurfaceTarget::Texture1D:
glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, glTextureSubImage1D(texture.handle, mip_map, x0, static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
&gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::Texture2D: case SurfaceTarget::Texture2D:
glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, glTextureSubImage2D(texture.handle, mip_map, x0, y0,
static_cast<GLsizei>(rect.GetWidth()), static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
&gl_buffer[mip_map][buffer_offset]); &gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::Texture3D: case SurfaceTarget::Texture3D:
glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0,
static_cast<GLsizei>(rect.GetWidth()), static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map),
tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::Texture2DArray: case SurfaceTarget::Texture2DArray:
case SurfaceTarget::TextureCubeArray: case SurfaceTarget::TextureCubeArray:
glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0,
static_cast<GLsizei>(rect.GetWidth()), static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
tuple.type, &gl_buffer[mip_map][buffer_offset]); tuple.type, &gl_buffer[mip_map][buffer_offset]);
break; break;
case SurfaceTarget::TextureCubemap: { case SurfaceTarget::TextureCubemap: {
std::size_t start = buffer_offset; std::size_t start = buffer_offset;
for (std::size_t face = 0; face < params.depth; ++face) { for (std::size_t face = 0; face < params.depth; ++face) {
glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face),
x0, y0, static_cast<GLsizei>(rect.GetWidth()), static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, static_cast<GLsizei>(rect.GetHeight()), 1, tuple.format,
&gl_buffer[mip_map][buffer_offset]); tuple.type, &gl_buffer[mip_map][buffer_offset]);
buffer_offset += params.LayerSizeGL(mip_map); buffer_offset += params.LayerSizeGL(mip_map);
} }
break; break;
@ -865,9 +834,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
static_cast<u32>(params.target)); static_cast<u32>(params.target));
UNREACHABLE(); UNREACHABLE();
glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), glTextureSubImage2D(texture.handle, mip_map, x0, y0,
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, static_cast<GLsizei>(rect.GetWidth()),
&gl_buffer[mip_map][buffer_offset]); static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
&gl_buffer[mip_map][buffer_offset]);
} }
} }
@ -877,29 +847,16 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
void CachedSurface::EnsureTextureView() { void CachedSurface::EnsureTextureView() {
if (texture_view.handle != 0) if (texture_view.handle != 0)
return; return;
// Compressed texture are not being created with immutable storage
UNIMPLEMENTED_IF(gl_is_compressed);
const GLenum target{TargetLayer()}; const GLenum target{TargetLayer()};
const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u};
constexpr GLuint min_layer = 0; constexpr GLuint min_layer = 0;
constexpr GLuint min_level = 0; constexpr GLuint min_level = 0;
texture_view.Create(); glGenTextures(1, &texture_view.handle);
glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0,
params.max_mip_level, min_layer, num_layers); params.max_mip_level, 0, 1);
ApplyTextureDefaults(texture_view.handle, params.max_mip_level);
OpenGLState cur_state = OpenGLState::GetCurState();
const auto& old_tex = cur_state.texture_units[0];
SCOPE_EXIT({
cur_state.texture_units[0] = old_tex;
cur_state.Apply();
});
cur_state.texture_units[0].texture = texture_view.handle;
cur_state.texture_units[0].target = target;
cur_state.Apply();
ApplyTextureDefaults(target, params.max_mip_level);
} }
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));

View file

@ -393,7 +393,6 @@ private:
SurfaceParams params{}; SurfaceParams params{};
GLenum gl_target{}; GLenum gl_target{};
GLenum gl_internal_format{}; GLenum gl_internal_format{};
bool gl_is_compressed{};
std::size_t cached_size_in_bytes{}; std::size_t cached_size_in_bytes{};
}; };

View file

@ -15,12 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R
namespace OpenGL { namespace OpenGL {
void OGLTexture::Create() { void OGLTexture::Create(GLenum target) {
if (handle != 0) if (handle != 0)
return; return;
MICROPROFILE_SCOPE(OpenGL_ResourceCreation); MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
glGenTextures(1, &handle); glCreateTextures(target, 1, &handle);
} }
void OGLTexture::Release() { void OGLTexture::Release() {

View file

@ -28,7 +28,7 @@ public:
} }
/// Creates a new internal OpenGL resource and stores the handle /// Creates a new internal OpenGL resource and stores the handle
void Create(); void Create(GLenum target);
/// Deletes the internal OpenGL resource /// Deletes the internal OpenGL resource
void Release(); void Release();

View file

@ -171,10 +171,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
Memory::GetPointer(framebuffer_addr), Memory::GetPointer(framebuffer_addr),
gl_framebuffer_data.data(), true); gl_framebuffer_data.data(), true);
state.texture_units[0].texture = screen_info.texture.resource.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
// Update existing texture // Update existing texture
@ -182,14 +178,11 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
// they differ from the LCD resolution. // they differ from the LCD resolution.
// TODO: Applications could theoretically crash yuzu here by specifying too large // TODO: Applications could theoretically crash yuzu here by specifying too large
// framebuffer sizes. We should make sure that this cannot happen. // framebuffer sizes. We should make sure that this cannot happen.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width,
screen_info.texture.gl_format, screen_info.texture.gl_type, framebuffer.height, screen_info.texture.gl_format,
gl_framebuffer_data.data()); screen_info.texture.gl_type, gl_framebuffer_data.data());
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
state.texture_units[0].texture = 0;
state.Apply();
} }
} }
@ -199,17 +192,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
*/ */
void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture) { const TextureInfo& texture) {
state.texture_units[0].texture = texture.resource.handle; const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
state.Apply(); glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
glActiveTexture(GL_TEXTURE0);
u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
// Update existing texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
state.texture_units[0].texture = 0;
state.Apply();
} }
/** /**
@ -249,26 +233,13 @@ void RendererOpenGL::InitOpenGLObjects() {
sizeof(ScreenRectVertex)); sizeof(ScreenRectVertex));
// Allocate textures for the screen // Allocate textures for the screen
screen_info.texture.resource.Create(); screen_info.texture.resource.Create(GL_TEXTURE_2D);
// Allocation of storage is deferred until the first frame, when we const GLuint texture = screen_info.texture.resource.handle;
// know the framebuffer size. glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
state.texture_units[0].texture = screen_info.texture.resource.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
screen_info.display_texture = screen_info.texture.resource.handle; screen_info.display_texture = screen_info.texture.resource.handle;
state.texture_units[0].texture = 0;
state.Apply();
// Clear screen to black // Clear screen to black
LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
} }
@ -284,20 +255,19 @@ void RendererOpenGL::CreateRasterizer() {
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer) { const Tegra::FramebufferConfig& framebuffer) {
texture.width = framebuffer.width; texture.width = framebuffer.width;
texture.height = framebuffer.height; texture.height = framebuffer.height;
GLint internal_format; GLint internal_format;
switch (framebuffer.pixel_format) { switch (framebuffer.pixel_format) {
case Tegra::FramebufferConfig::PixelFormat::ABGR8: case Tegra::FramebufferConfig::PixelFormat::ABGR8:
internal_format = GL_RGBA; internal_format = GL_RGBA8;
texture.gl_format = GL_RGBA; texture.gl_format = GL_RGBA;
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
gl_framebuffer_data.resize(texture.width * texture.height * 4); gl_framebuffer_data.resize(texture.width * texture.height * 4);
break; break;
default: default:
internal_format = GL_RGBA; internal_format = GL_RGBA8;
texture.gl_format = GL_RGBA; texture.gl_format = GL_RGBA;
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
gl_framebuffer_data.resize(texture.width * texture.height * 4); gl_framebuffer_data.resize(texture.width * texture.height * 4);
@ -306,15 +276,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
UNREACHABLE(); UNREACHABLE();
} }
state.texture_units[0].texture = texture.resource.handle; texture.resource.Release();
state.Apply(); texture.resource.Create(GL_TEXTURE_2D);
glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
glActiveTexture(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
texture.gl_format, texture.gl_type, nullptr);
state.texture_units[0].texture = 0;
state.Apply();
} }
void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w,