summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-08 16:14:46 -0400
committerGravatar GitHub2018-09-08 16:14:46 -0400
commitaf074ee422a5350a3adb7586fab3c3fb5ed6bdc4 (patch)
tree6425e9818766c88b2fe33aa559b4815b3f6cf9f1
parentMerge pull request #1265 from zhaowenlan1779/patch-1 (diff)
parentgl_rasterizer_cache: Improve accuracy of RecreateSurface for non-2D textures. (diff)
downloadyuzu-af074ee422a5350a3adb7586fab3c3fb5ed6bdc4.tar.gz
yuzu-af074ee422a5350a3adb7586fab3c3fb5ed6bdc4.tar.xz
yuzu-af074ee422a5350a3adb7586fab3c3fb5ed6bdc4.zip
Merge pull request #1256 from bunnei/tex-target-support
Initial support for non-2D textures
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp16
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp364
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h43
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp125
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h50
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_state.h8
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp20
-rw-r--r--src/video_core/textures/texture.h12
11 files changed, 422 insertions, 229 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index e63ad4d46..1308080b5 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -293,10 +293,6 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
293 tic_entry.header_version == Texture::TICHeaderVersion::Pitch, 293 tic_entry.header_version == Texture::TICHeaderVersion::Pitch,
294 "TIC versions other than BlockLinear or Pitch are unimplemented"); 294 "TIC versions other than BlockLinear or Pitch are unimplemented");
295 295
296 ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) ||
297 (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap),
298 "Texture types other than Texture2D are unimplemented");
299
300 auto r_type = tic_entry.r_type.Value(); 296 auto r_type = tic_entry.r_type.Value();
301 auto g_type = tic_entry.g_type.Value(); 297 auto g_type = tic_entry.g_type.Value();
302 auto b_type = tic_entry.b_type.Value(); 298 auto b_type = tic_entry.b_type.Value();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0c3bbc475..e6d6917fa 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -586,7 +586,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
586void RasterizerOpenGL::SamplerInfo::Create() { 586void RasterizerOpenGL::SamplerInfo::Create() {
587 sampler.Create(); 587 sampler.Create();
588 mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear; 588 mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear;
589 wrap_u = wrap_v = Tegra::Texture::WrapMode::Wrap; 589 wrap_u = wrap_v = wrap_p = Tegra::Texture::WrapMode::Wrap;
590 590
591 // default is GL_LINEAR_MIPMAP_LINEAR 591 // default is GL_LINEAR_MIPMAP_LINEAR
592 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 592 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -613,8 +613,13 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
613 wrap_v = config.wrap_v; 613 wrap_v = config.wrap_v;
614 glSamplerParameteri(s, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(wrap_v)); 614 glSamplerParameteri(s, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(wrap_v));
615 } 615 }
616 if (wrap_p != config.wrap_p) {
617 wrap_p = config.wrap_p;
618 glSamplerParameteri(s, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p));
619 }
616 620
617 if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border) { 621 if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border ||
622 wrap_p == Tegra::Texture::WrapMode::Border) {
618 const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g, 623 const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g,
619 config.border_color_b, config.border_color_a}}; 624 config.border_color_b, config.border_color_a}};
620 if (border_color != new_border_color) { 625 if (border_color != new_border_color) {
@@ -698,14 +703,15 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
698 const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset()); 703 const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset());
699 704
700 if (!texture.enabled) { 705 if (!texture.enabled) {
701 state.texture_units[current_bindpoint].texture_2d = 0; 706 state.texture_units[current_bindpoint].texture = 0;
702 continue; 707 continue;
703 } 708 }
704 709
705 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); 710 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
706 Surface surface = res_cache.GetTextureSurface(texture); 711 Surface surface = res_cache.GetTextureSurface(texture);
707 if (surface != nullptr) { 712 if (surface != nullptr) {
708 state.texture_units[current_bindpoint].texture_2d = surface->Texture().handle; 713 state.texture_units[current_bindpoint].texture = surface->Texture().handle;
714 state.texture_units[current_bindpoint].target = surface->Target();
709 state.texture_units[current_bindpoint].swizzle.r = 715 state.texture_units[current_bindpoint].swizzle.r =
710 MaxwellToGL::SwizzleSource(texture.tic.x_source); 716 MaxwellToGL::SwizzleSource(texture.tic.x_source);
711 state.texture_units[current_bindpoint].swizzle.g = 717 state.texture_units[current_bindpoint].swizzle.g =
@@ -716,7 +722,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
716 MaxwellToGL::SwizzleSource(texture.tic.w_source); 722 MaxwellToGL::SwizzleSource(texture.tic.w_source);
717 } else { 723 } else {
718 // Can occur when texture addr is null or its memory is unmapped/invalid 724 // Can occur when texture addr is null or its memory is unmapped/invalid
719 state.texture_units[current_bindpoint].texture_2d = 0; 725 state.texture_units[current_bindpoint].texture = 0;
720 } 726 }
721 } 727 }
722 728
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 9c30dc0e8..c6bb1516b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -93,6 +93,7 @@ private:
93 Tegra::Texture::TextureFilter min_filter; 93 Tegra::Texture::TextureFilter min_filter;
94 Tegra::Texture::WrapMode wrap_u; 94 Tegra::Texture::WrapMode wrap_u;
95 Tegra::Texture::WrapMode wrap_v; 95 Tegra::Texture::WrapMode wrap_v;
96 Tegra::Texture::WrapMode wrap_p;
96 GLvec4 border_color; 97 GLvec4 border_color;
97 }; 98 };
98 99
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index f6b2c5a86..360fb0cd5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -7,6 +7,7 @@
7 7
8#include "common/alignment.h" 8#include "common/alignment.h"
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/logging/log.h"
10#include "common/microprofile.h" 11#include "common/microprofile.h"
11#include "common/scope_exit.h" 12#include "common/scope_exit.h"
12#include "core/core.h" 13#include "core/core.h"
@@ -51,10 +52,12 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
51 params.type = GetFormatType(params.pixel_format); 52 params.type = GetFormatType(params.pixel_format);
52 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); 53 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
53 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); 54 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
55 params.depth = config.tic.Depth();
54 params.unaligned_height = config.tic.Height(); 56 params.unaligned_height = config.tic.Height();
55 params.size_in_bytes = params.SizeInBytes(); 57 params.size_in_bytes = params.SizeInBytes();
56 params.cache_width = Common::AlignUp(params.width, 16); 58 params.cache_width = Common::AlignUp(params.width, 8);
57 params.cache_height = Common::AlignUp(params.height, 16); 59 params.cache_height = Common::AlignUp(params.height, 8);
60 params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
58 return params; 61 return params;
59} 62}
60 63
@@ -69,10 +72,12 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
69 params.type = GetFormatType(params.pixel_format); 72 params.type = GetFormatType(params.pixel_format);
70 params.width = config.width; 73 params.width = config.width;
71 params.height = config.height; 74 params.height = config.height;
75 params.depth = 1;
72 params.unaligned_height = config.height; 76 params.unaligned_height = config.height;
73 params.size_in_bytes = params.SizeInBytes(); 77 params.size_in_bytes = params.SizeInBytes();
74 params.cache_width = Common::AlignUp(params.width, 16); 78 params.cache_width = Common::AlignUp(params.width, 8);
75 params.cache_height = Common::AlignUp(params.height, 16); 79 params.cache_height = Common::AlignUp(params.height, 8);
80 params.target = SurfaceTarget::Texture2D;
76 return params; 81 return params;
77} 82}
78 83
@@ -86,13 +91,14 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
86 params.pixel_format = PixelFormatFromDepthFormat(format); 91 params.pixel_format = PixelFormatFromDepthFormat(format);
87 params.component_type = ComponentTypeFromDepthFormat(format); 92 params.component_type = ComponentTypeFromDepthFormat(format);
88 params.type = GetFormatType(params.pixel_format); 93 params.type = GetFormatType(params.pixel_format);
89 params.size_in_bytes = params.SizeInBytes();
90 params.width = zeta_width; 94 params.width = zeta_width;
91 params.height = zeta_height; 95 params.height = zeta_height;
96 params.depth = 1;
92 params.unaligned_height = zeta_height; 97 params.unaligned_height = zeta_height;
93 params.size_in_bytes = params.SizeInBytes(); 98 params.size_in_bytes = params.SizeInBytes();
94 params.cache_width = Common::AlignUp(params.width, 16); 99 params.cache_width = Common::AlignUp(params.width, 8);
95 params.cache_height = Common::AlignUp(params.height, 16); 100 params.cache_height = Common::AlignUp(params.height, 8);
101 params.target = SurfaceTarget::Texture2D;
96 return params; 102 return params;
97} 103}
98 104
@@ -166,6 +172,26 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
166 ComponentType::Float, false}, // Z32FS8 172 ComponentType::Float, false}, // Z32FS8
167}}; 173}};
168 174
175static GLenum SurfaceTargetToGL(SurfaceParams::SurfaceTarget target) {
176 switch (target) {
177 case SurfaceParams::SurfaceTarget::Texture1D:
178 return GL_TEXTURE_1D;
179 case SurfaceParams::SurfaceTarget::Texture2D:
180 return GL_TEXTURE_2D;
181 case SurfaceParams::SurfaceTarget::Texture3D:
182 return GL_TEXTURE_3D;
183 case SurfaceParams::SurfaceTarget::Texture1DArray:
184 return GL_TEXTURE_1D_ARRAY;
185 case SurfaceParams::SurfaceTarget::Texture2DArray:
186 return GL_TEXTURE_2D_ARRAY;
187 case SurfaceParams::SurfaceTarget::TextureCubemap:
188 return GL_TEXTURE_CUBE_MAP;
189 }
190 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
191 UNREACHABLE();
192 return {};
193}
194
169static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { 195static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
170 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); 196 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
171 auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)]; 197 auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
@@ -220,7 +246,8 @@ static bool IsFormatBCn(PixelFormat format) {
220} 246}
221 247
222template <bool morton_to_gl, PixelFormat format> 248template <bool morton_to_gl, PixelFormat format>
223void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_buffer, VAddr addr) { 249void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, size_t gl_buffer_size,
250 VAddr addr) {
224 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT; 251 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT;
225 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 252 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
226 253
@@ -230,18 +257,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_bu
230 const u32 tile_size{IsFormatBCn(format) ? 4U : 1U}; 257 const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
231 const std::vector<u8> data = Tegra::Texture::UnswizzleTexture( 258 const std::vector<u8> data = Tegra::Texture::UnswizzleTexture(
232 addr, tile_size, bytes_per_pixel, stride, height, block_height); 259 addr, tile_size, bytes_per_pixel, stride, height, block_height);
233 const size_t size_to_copy{std::min(gl_buffer.size(), data.size())}; 260 const size_t size_to_copy{std::min(gl_buffer_size, data.size())};
234 gl_buffer.assign(data.begin(), data.begin() + size_to_copy); 261 memcpy(gl_buffer, data.data(), size_to_copy);
235 } else { 262 } else {
236 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should 263 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
237 // check the configuration for this and perform more generic un/swizzle 264 // check the configuration for this and perform more generic un/swizzle
238 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); 265 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
239 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, 266 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel,
240 Memory::GetPointer(addr), gl_buffer.data(), morton_to_gl); 267 Memory::GetPointer(addr), gl_buffer, morton_to_gl);
241 } 268 }
242} 269}
243 270
244static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr), 271static constexpr std::array<void (*)(u32, u32, u32, u8*, size_t, VAddr),
245 SurfaceParams::MaxPixelFormat> 272 SurfaceParams::MaxPixelFormat>
246 morton_to_gl_fns = { 273 morton_to_gl_fns = {
247 // clang-format off 274 // clang-format off
@@ -298,7 +325,7 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr),
298 // clang-format on 325 // clang-format on
299}; 326};
300 327
301static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr), 328static constexpr std::array<void (*)(u32, u32, u32, u8*, size_t, VAddr),
302 SurfaceParams::MaxPixelFormat> 329 SurfaceParams::MaxPixelFormat>
303 gl_to_morton_fns = { 330 gl_to_morton_fns = {
304 // clang-format off 331 // clang-format off
@@ -357,33 +384,6 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr),
357 // clang-format on 384 // clang-format on
358}; 385};
359 386
360// Allocate an uninitialized texture of appropriate size and format for the surface
361static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tuple, u32 width,
362 u32 height) {
363 OpenGLState cur_state = OpenGLState::GetCurState();
364
365 // Keep track of previous texture bindings
366 GLuint old_tex = cur_state.texture_units[0].texture_2d;
367 cur_state.texture_units[0].texture_2d = texture;
368 cur_state.Apply();
369 glActiveTexture(GL_TEXTURE0);
370
371 if (!format_tuple.compressed) {
372 // Only pre-create the texture for non-compressed textures.
373 glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
374 format_tuple.format, format_tuple.type, nullptr);
375 }
376
377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
381
382 // Restore previous texture bindings
383 cur_state.texture_units[0].texture_2d = old_tex;
384 cur_state.Apply();
385}
386
387static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, 387static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex,
388 const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, 388 const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type,
389 GLuint read_fb_handle, GLuint draw_fb_handle) { 389 GLuint read_fb_handle, GLuint draw_fb_handle) {
@@ -438,12 +438,56 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec
438 return true; 438 return true;
439} 439}
440 440
441CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { 441CachedSurface::CachedSurface(const SurfaceParams& params)
442 : params(params), gl_target(SurfaceTargetToGL(params.target)) {
442 texture.Create(); 443 texture.Create();
443 const auto& rect{params.GetRect()}; 444 const auto& rect{params.GetRect()};
444 AllocateSurfaceTexture(texture.handle, 445
445 GetFormatTuple(params.pixel_format, params.component_type), 446 // Keep track of previous texture bindings
446 rect.GetWidth(), rect.GetHeight()); 447 OpenGLState cur_state = OpenGLState::GetCurState();
448 const auto& old_tex = cur_state.texture_units[0];
449 SCOPE_EXIT({
450 cur_state.texture_units[0] = old_tex;
451 cur_state.Apply();
452 });
453
454 cur_state.texture_units[0].texture = texture.handle;
455 cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
456 cur_state.Apply();
457 glActiveTexture(GL_TEXTURE0);
458
459 const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
460 if (!format_tuple.compressed) {
461 // Only pre-create the texture for non-compressed textures.
462 switch (params.target) {
463 case SurfaceParams::SurfaceTarget::Texture1D:
464 glTexImage1D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
465 rect.GetWidth(), 0, format_tuple.format, format_tuple.type, nullptr);
466 break;
467 case SurfaceParams::SurfaceTarget::Texture2D:
468 glTexImage2D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
469 rect.GetWidth(), rect.GetHeight(), 0, format_tuple.format,
470 format_tuple.type, nullptr);
471 break;
472 case SurfaceParams::SurfaceTarget::Texture3D:
473 case SurfaceParams::SurfaceTarget::Texture2DArray:
474 glTexImage3D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
475 rect.GetWidth(), rect.GetHeight(), params.depth, 0, format_tuple.format,
476 format_tuple.type, nullptr);
477 break;
478 default:
479 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
480 static_cast<u32>(params.target));
481 UNREACHABLE();
482 glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(),
483 rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr);
484 }
485 }
486
487 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0);
488 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
489 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
490 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
447} 491}
448 492
449static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { 493static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
@@ -514,23 +558,6 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
514 } 558 }
515} 559}
516 560
517/**
518 * Helper function to perform software conversion (as needed) when flushing a buffer to Switch
519 * memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with
520 * typical desktop GPUs.
521 */
522static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& /*data*/, PixelFormat pixel_format,
523 u32 /*width*/, u32 /*height*/) {
524 switch (pixel_format) {
525 case PixelFormat::ASTC_2D_4X4:
526 case PixelFormat::S8Z24:
527 LOG_CRITICAL(Render_OpenGL, "Unimplemented pixel_format={}",
528 static_cast<u32>(pixel_format));
529 UNREACHABLE();
530 break;
531 }
532}
533
534MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); 561MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
535void CachedSurface::LoadGLBuffer() { 562void CachedSurface::LoadGLBuffer() {
536 ASSERT(params.type != SurfaceType::Fill); 563 ASSERT(params.type != SurfaceType::Fill);
@@ -545,13 +572,24 @@ void CachedSurface::LoadGLBuffer() {
545 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); 572 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
546 573
547 if (params.is_tiled) { 574 if (params.is_tiled) {
548 gl_buffer.resize(copy_size); 575 // TODO(bunnei): This only unswizzles and copies a 2D texture - we do not yet know how to do
576 // this for 3D textures, etc.
577 switch (params.target) {
578 case SurfaceParams::SurfaceTarget::Texture2D:
579 // Pass impl. to the fallback code below
580 break;
581 default:
582 LOG_CRITICAL(HW_GPU, "Unimplemented tiled load for target={}",
583 static_cast<u32>(params.target));
584 UNREACHABLE();
585 }
549 586
587 gl_buffer.resize(params.depth * copy_size);
550 morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( 588 morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
551 params.width, params.block_height, params.height, gl_buffer, params.addr); 589 params.width, params.block_height, params.height, gl_buffer.data(), copy_size,
590 params.addr);
552 } else { 591 } else {
553 const u8* const texture_src_data_end = texture_src_data + copy_size; 592 const u8* const texture_src_data_end{texture_src_data + (params.depth * copy_size)};
554
555 gl_buffer.assign(texture_src_data, texture_src_data_end); 593 gl_buffer.assign(texture_src_data, texture_src_data_end);
556 } 594 }
557 595
@@ -560,23 +598,7 @@ void CachedSurface::LoadGLBuffer() {
560 598
561MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); 599MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
562void CachedSurface::FlushGLBuffer() { 600void CachedSurface::FlushGLBuffer() {
563 u8* const dst_buffer = Memory::GetPointer(params.addr); 601 ASSERT_MSG(false, "Unimplemented");
564
565 ASSERT(dst_buffer);
566 ASSERT(gl_buffer.size() ==
567 params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
568
569 MICROPROFILE_SCOPE(OpenGL_SurfaceFlush);
570
571 ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer, params.pixel_format, params.width,
572 params.height);
573
574 if (!params.is_tiled) {
575 std::memcpy(dst_buffer, gl_buffer.data(), params.size_in_bytes);
576 } else {
577 gl_to_morton_fns[static_cast<size_t>(params.pixel_format)](
578 params.width, params.block_height, params.height, gl_buffer, params.addr);
579 }
580} 602}
581 603
582MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); 604MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
@@ -587,7 +609,7 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
587 MICROPROFILE_SCOPE(OpenGL_TextureUL); 609 MICROPROFILE_SCOPE(OpenGL_TextureUL);
588 610
589 ASSERT(gl_buffer.size() == 611 ASSERT(gl_buffer.size() ==
590 params.width * params.height * GetGLBytesPerPixel(params.pixel_format)); 612 params.width * params.height * GetGLBytesPerPixel(params.pixel_format) * params.depth);
591 613
592 const auto& rect{params.GetRect()}; 614 const auto& rect{params.GetRect()};
593 615
@@ -600,8 +622,13 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
600 GLuint target_tex = texture.handle; 622 GLuint target_tex = texture.handle;
601 OpenGLState cur_state = OpenGLState::GetCurState(); 623 OpenGLState cur_state = OpenGLState::GetCurState();
602 624
603 GLuint old_tex = cur_state.texture_units[0].texture_2d; 625 const auto& old_tex = cur_state.texture_units[0];
604 cur_state.texture_units[0].texture_2d = target_tex; 626 SCOPE_EXIT({
627 cur_state.texture_units[0] = old_tex;
628 cur_state.Apply();
629 });
630 cur_state.texture_units[0].texture = target_tex;
631 cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
605 cur_state.Apply(); 632 cur_state.Apply();
606 633
607 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT 634 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
@@ -610,74 +637,68 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
610 637
611 glActiveTexture(GL_TEXTURE0); 638 glActiveTexture(GL_TEXTURE0);
612 if (tuple.compressed) { 639 if (tuple.compressed) {
613 glCompressedTexImage2D( 640 switch (params.target) {
614 GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width), 641 case SurfaceParams::SurfaceTarget::Texture2D:
615 static_cast<GLsizei>(params.height), 0, static_cast<GLsizei>(params.size_in_bytes), 642 glCompressedTexImage2D(
616 &gl_buffer[buffer_offset]); 643 SurfaceTargetToGL(params.target), 0, tuple.internal_format,
644 static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0,
645 static_cast<GLsizei>(params.size_in_bytes), &gl_buffer[buffer_offset]);
646 break;
647 case SurfaceParams::SurfaceTarget::Texture3D:
648 case SurfaceParams::SurfaceTarget::Texture2DArray:
649 glCompressedTexImage3D(
650 SurfaceTargetToGL(params.target), 0, tuple.internal_format,
651 static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height),
652 static_cast<GLsizei>(params.depth), 0, static_cast<GLsizei>(params.size_in_bytes),
653 &gl_buffer[buffer_offset]);
654 break;
655 default:
656 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
657 static_cast<u32>(params.target));
658 UNREACHABLE();
659 glCompressedTexImage2D(
660 GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width),
661 static_cast<GLsizei>(params.height), 0, static_cast<GLsizei>(params.size_in_bytes),
662 &gl_buffer[buffer_offset]);
663 }
617 } else { 664 } else {
618 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
619 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
620 &gl_buffer[buffer_offset]);
621 }
622
623 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
624
625 cur_state.texture_units[0].texture_2d = old_tex;
626 cur_state.Apply();
627}
628
629MICROPROFILE_DEFINE(OpenGL_TextureDL, "OpenGL", "Texture Download", MP_RGB(128, 192, 64));
630void CachedSurface::DownloadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
631 if (params.type == SurfaceType::Fill)
632 return;
633
634 MICROPROFILE_SCOPE(OpenGL_TextureDL);
635
636 gl_buffer.resize(params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
637
638 OpenGLState state = OpenGLState::GetCurState();
639 OpenGLState prev_state = state;
640 SCOPE_EXIT({ prev_state.Apply(); });
641 665
642 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); 666 switch (params.target) {
643 667 case SurfaceParams::SurfaceTarget::Texture1D:
644 // Ensure no bad interactions with GL_PACK_ALIGNMENT 668 glTexSubImage1D(SurfaceTargetToGL(params.target), 0, x0,
645 ASSERT(params.width * GetGLBytesPerPixel(params.pixel_format) % 4 == 0); 669 static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type,
646 glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.width)); 670 &gl_buffer[buffer_offset]);
647 671 break;
648 const auto& rect{params.GetRect()}; 672 case SurfaceParams::SurfaceTarget::Texture2D:
649 size_t buffer_offset = 673 glTexSubImage2D(SurfaceTargetToGL(params.target), 0, x0, y0,
650 (rect.bottom * params.width + rect.left) * GetGLBytesPerPixel(params.pixel_format); 674 static_cast<GLsizei>(rect.GetWidth()),
651 675 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
652 state.UnbindTexture(texture.handle); 676 &gl_buffer[buffer_offset]);
653 state.draw.read_framebuffer = read_fb_handle; 677 break;
654 state.Apply(); 678 case SurfaceParams::SurfaceTarget::Texture3D:
655 679 case SurfaceParams::SurfaceTarget::Texture2DArray:
656 if (params.type == SurfaceType::ColorTexture) { 680 glTexSubImage3D(SurfaceTargetToGL(params.target), 0, x0, y0, 0,
657 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 681 static_cast<GLsizei>(rect.GetWidth()),
658 texture.handle, 0); 682 static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
659 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 683 tuple.type, &gl_buffer[buffer_offset]);
660 0); 684 break;
661 } else if (params.type == SurfaceType::Depth) { 685 default:
662 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 686 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
663 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 687 static_cast<u32>(params.target));
664 texture.handle, 0); 688 UNREACHABLE();
665 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 689 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
666 } else { 690 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
667 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 691 &gl_buffer[buffer_offset]);
668 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 692 }
669 texture.handle, 0);
670 } 693 }
671 glReadPixels(static_cast<GLint>(rect.left), static_cast<GLint>(rect.bottom),
672 static_cast<GLsizei>(rect.GetWidth()), static_cast<GLsizei>(rect.GetHeight()),
673 tuple.format, tuple.type, &gl_buffer[buffer_offset]);
674 694
675 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 695 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
676} 696}
677 697
678RasterizerCacheOpenGL::RasterizerCacheOpenGL() { 698RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
679 read_framebuffer.Create(); 699 read_framebuffer.Create();
680 draw_framebuffer.Create(); 700 draw_framebuffer.Create();
701 copy_pbo.Create();
681} 702}
682 703
683Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) { 704Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
@@ -748,7 +769,6 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
748} 769}
749 770
750void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) { 771void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) {
751 surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle);
752 surface->FlushGLBuffer(); 772 surface->FlushGLBuffer();
753} 773}
754 774
@@ -809,8 +829,8 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
809 // If format is unchanged, we can do a faster blit without reinterpreting pixel data 829 // If format is unchanged, we can do a faster blit without reinterpreting pixel data
810 if (params.pixel_format == new_params.pixel_format) { 830 if (params.pixel_format == new_params.pixel_format) {
811 BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle, 831 BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle,
812 new_surface->GetSurfaceParams().GetRect(), params.type, 832 params.GetRect(), params.type, read_framebuffer.handle,
813 read_framebuffer.handle, draw_framebuffer.handle); 833 draw_framebuffer.handle);
814 return new_surface; 834 return new_surface;
815 } 835 }
816 836
@@ -821,12 +841,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
821 841
822 size_t buffer_size = std::max(params.SizeInBytes(), new_params.SizeInBytes()); 842 size_t buffer_size = std::max(params.SizeInBytes(), new_params.SizeInBytes());
823 843
824 // Use a Pixel Buffer Object to download the previous texture and then upload it to the new 844 glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo.handle);
825 // one using the new format.
826 OGLBuffer pbo;
827 pbo.Create();
828
829 glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle);
830 glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB); 845 glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
831 if (source_format.compressed) { 846 if (source_format.compressed) {
832 glGetCompressedTextureImage(surface->Texture().handle, 0, 847 glGetCompressedTextureImage(surface->Texture().handle, 0,
@@ -845,8 +860,8 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
845 // of the data in this case. Games like Super Mario Odyssey seem to hit this case 860 // of the data in this case. Games like Super Mario Odyssey seem to hit this case
846 // when drawing, it re-uses the memory of a previous texture as a bigger framebuffer 861 // when drawing, it re-uses the memory of a previous texture as a bigger framebuffer
847 // but it doesn't clear it beforehand, the texture is already full of zeros. 862 // but it doesn't clear it beforehand, the texture is already full of zeros.
848 LOG_CRITICAL(HW_GPU, "Trying to upload extra texture data from the CPU during " 863 LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during "
849 "reinterpretation but the texture is tiled."); 864 "reinterpretation but the texture is tiled.");
850 } 865 }
851 size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes(); 866 size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
852 std::vector<u8> data(remaining_size); 867 std::vector<u8> data(remaining_size);
@@ -859,21 +874,38 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
859 874
860 const auto& dest_rect{new_params.GetRect()}; 875 const auto& dest_rect{new_params.GetRect()};
861 876
862 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.handle); 877 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, copy_pbo.handle);
863 if (dest_format.compressed) { 878 if (dest_format.compressed) {
864 glCompressedTexSubImage2D( 879 LOG_CRITICAL(HW_GPU, "Compressed copy is unimplemented!");
865 GL_TEXTURE_2D, 0, 0, 0, static_cast<GLsizei>(dest_rect.GetWidth()), 880 UNREACHABLE();
866 static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
867 static_cast<GLsizei>(new_params.SizeInBytes()), nullptr);
868 } else { 881 } else {
869 glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0, 882 switch (new_params.target) {
870 static_cast<GLsizei>(dest_rect.GetWidth()), 883 case SurfaceParams::SurfaceTarget::Texture1D:
871 static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format, 884 glTextureSubImage1D(new_surface->Texture().handle, 0, 0,
872 dest_format.type, nullptr); 885 static_cast<GLsizei>(dest_rect.GetWidth()), dest_format.format,
886 dest_format.type, nullptr);
887 break;
888 case SurfaceParams::SurfaceTarget::Texture2D:
889 glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0,
890 static_cast<GLsizei>(dest_rect.GetWidth()),
891 static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
892 dest_format.type, nullptr);
893 break;
894 case SurfaceParams::SurfaceTarget::Texture3D:
895 case SurfaceParams::SurfaceTarget::Texture2DArray:
896 glTextureSubImage3D(new_surface->Texture().handle, 0, 0, 0, 0,
897 static_cast<GLsizei>(dest_rect.GetWidth()),
898 static_cast<GLsizei>(dest_rect.GetHeight()),
899 static_cast<GLsizei>(new_params.depth), dest_format.format,
900 dest_format.type, nullptr);
901 break;
902 default:
903 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
904 static_cast<u32>(params.target));
905 UNREACHABLE();
906 }
873 } 907 }
874 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 908 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
875
876 pbo.Release();
877 } 909 }
878 910
879 return new_surface; 911 return new_surface;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index aad75f200..8312b2c7a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -109,6 +109,33 @@ struct SurfaceParams {
109 Invalid = 4, 109 Invalid = 4,
110 }; 110 };
111 111
112 enum class SurfaceTarget {
113 Texture1D,
114 Texture2D,
115 Texture3D,
116 Texture1DArray,
117 Texture2DArray,
118 TextureCubemap,
119 };
120
121 static SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) {
122 switch (texture_type) {
123 case Tegra::Texture::TextureType::Texture1D:
124 return SurfaceTarget::Texture1D;
125 case Tegra::Texture::TextureType::Texture2D:
126 case Tegra::Texture::TextureType::Texture2DNoMipmap:
127 return SurfaceTarget::Texture2D;
128 case Tegra::Texture::TextureType::Texture1DArray:
129 return SurfaceTarget::Texture1DArray;
130 case Tegra::Texture::TextureType::Texture2DArray:
131 return SurfaceTarget::Texture2DArray;
132 default:
133 LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", static_cast<u32>(texture_type));
134 UNREACHABLE();
135 return SurfaceTarget::Texture2D;
136 }
137 }
138
112 /** 139 /**
113 * Gets the compression factor for the specified PixelFormat. This applies to just the 140 * Gets the compression factor for the specified PixelFormat. This applies to just the
114 * "compressed width" and "compressed height", not the overall compression factor of a 141 * "compressed width" and "compressed height", not the overall compression factor of a
@@ -635,7 +662,7 @@ struct SurfaceParams {
635 ASSERT(width % compression_factor == 0); 662 ASSERT(width % compression_factor == 0);
636 ASSERT(height % compression_factor == 0); 663 ASSERT(height % compression_factor == 0);
637 return (width / compression_factor) * (height / compression_factor) * 664 return (width / compression_factor) * (height / compression_factor) *
638 GetFormatBpp(pixel_format) / CHAR_BIT; 665 GetFormatBpp(pixel_format) * depth / CHAR_BIT;
639 } 666 }
640 667
641 /// Creates SurfaceParams from a texture configuration 668 /// Creates SurfaceParams from a texture configuration
@@ -664,8 +691,10 @@ struct SurfaceParams {
664 SurfaceType type; 691 SurfaceType type;
665 u32 width; 692 u32 width;
666 u32 height; 693 u32 height;
694 u32 depth;
667 u32 unaligned_height; 695 u32 unaligned_height;
668 size_t size_in_bytes; 696 size_t size_in_bytes;
697 SurfaceTarget target;
669 698
670 // Parameters used for caching only 699 // Parameters used for caching only
671 u32 cache_width; 700 u32 cache_width;
@@ -709,6 +738,10 @@ public:
709 return texture; 738 return texture;
710 } 739 }
711 740
741 GLenum Target() const {
742 return gl_target;
743 }
744
712 static constexpr unsigned int GetGLBytesPerPixel(SurfaceParams::PixelFormat format) { 745 static constexpr unsigned int GetGLBytesPerPixel(SurfaceParams::PixelFormat format) {
713 if (format == SurfaceParams::PixelFormat::Invalid) 746 if (format == SurfaceParams::PixelFormat::Invalid)
714 return 0; 747 return 0;
@@ -724,14 +757,14 @@ public:
724 void LoadGLBuffer(); 757 void LoadGLBuffer();
725 void FlushGLBuffer(); 758 void FlushGLBuffer();
726 759
727 // Upload/Download data in gl_buffer in/to this surface's texture 760 // Upload data in gl_buffer to this surface's texture
728 void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); 761 void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
729 void DownloadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
730 762
731private: 763private:
732 OGLTexture texture; 764 OGLTexture texture;
733 std::vector<u8> gl_buffer; 765 std::vector<u8> gl_buffer;
734 SurfaceParams params; 766 SurfaceParams params;
767 GLenum gl_target;
735}; 768};
736 769
737class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { 770class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
@@ -774,6 +807,10 @@ private:
774 807
775 OGLFramebuffer read_framebuffer; 808 OGLFramebuffer read_framebuffer;
776 OGLFramebuffer draw_framebuffer; 809 OGLFramebuffer draw_framebuffer;
810
811 /// Use a Pixel Buffer Object to download the previous texture and then upload it to the new one
812 /// using the new format.
813 OGLBuffer copy_pbo;
777}; 814};
778 815
779} // namespace OpenGL 816} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 841647ebe..172ba8335 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -443,13 +443,12 @@ public:
443 } 443 }
444 declarations.AddNewLine(); 444 declarations.AddNewLine();
445 445
446 // Append the sampler2D array for the used textures. 446 const auto& samplers = GetSamplers();
447 const size_t num_samplers = used_samplers.size(); 447 for (const auto& sampler : samplers) {
448 if (num_samplers > 0) { 448 declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() +
449 declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' + 449 ';');
450 std::to_string(num_samplers) + "];");
451 declarations.AddNewLine();
452 } 450 }
451 declarations.AddNewLine();
453 } 452 }
454 453
455 /// Returns a list of constant buffer declarations 454 /// Returns a list of constant buffer declarations
@@ -461,13 +460,14 @@ public:
461 } 460 }
462 461
463 /// Returns a list of samplers used in the shader 462 /// Returns a list of samplers used in the shader
464 std::vector<SamplerEntry> GetSamplers() const { 463 const std::vector<SamplerEntry>& GetSamplers() const {
465 return used_samplers; 464 return used_samplers;
466 } 465 }
467 466
468 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if 467 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
469 /// necessary. 468 /// necessary.
470 std::string AccessSampler(const Sampler& sampler) { 469 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
470 bool is_array) {
471 size_t offset = static_cast<size_t>(sampler.index.Value()); 471 size_t offset = static_cast<size_t>(sampler.index.Value());
472 472
473 // If this sampler has already been used, return the existing mapping. 473 // If this sampler has already been used, return the existing mapping.
@@ -476,12 +476,13 @@ public:
476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); 476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
477 477
478 if (itr != used_samplers.end()) { 478 if (itr != used_samplers.end()) {
479 ASSERT(itr->GetType() == type && itr->IsArray() == is_array);
479 return itr->GetName(); 480 return itr->GetName();
480 } 481 }
481 482
482 // Otherwise create a new mapping for this sampler 483 // Otherwise create a new mapping for this sampler
483 size_t next_index = used_samplers.size(); 484 size_t next_index = used_samplers.size();
484 SamplerEntry entry{stage, offset, next_index}; 485 SamplerEntry entry{stage, offset, next_index, type, is_array};
485 used_samplers.emplace_back(entry); 486 used_samplers.emplace_back(entry);
486 return entry.GetName(); 487 return entry.GetName();
487 } 488 }
@@ -722,8 +723,8 @@ private:
722 } 723 }
723 724
724 /// Generates code representing a texture sampler. 725 /// Generates code representing a texture sampler.
725 std::string GetSampler(const Sampler& sampler) { 726 std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) {
726 return regs.AccessSampler(sampler); 727 return regs.AccessSampler(sampler, type, is_array);
727 } 728 }
728 729
729 /** 730 /**
@@ -1753,10 +1754,35 @@ private:
1753 break; 1754 break;
1754 } 1755 }
1755 case OpCode::Id::TEX: { 1756 case OpCode::Id::TEX: {
1756 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1757 ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented");
1757 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1758 Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
1758 const std::string sampler = GetSampler(instr.sampler); 1759 std::string coord;
1759 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1760
1761 switch (texture_type) {
1762 case Tegra::Shader::TextureType::Texture1D: {
1763 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1764 coord = "float coords = " + x + ';';
1765 break;
1766 }
1767 case Tegra::Shader::TextureType::Texture2D: {
1768 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1769 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1770 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1771 break;
1772 }
1773 default:
1774 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1775 static_cast<u32>(texture_type));
1776 UNREACHABLE();
1777
1778 // Fallback to interpreting as a 2D texture for now
1779 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1780 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1781 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1782 texture_type = Tegra::Shader::TextureType::Texture2D;
1783 }
1784
1785 const std::string sampler = GetSampler(instr.sampler, texture_type, false);
1760 // Add an extra scope and declare the texture coords inside to prevent 1786 // Add an extra scope and declare the texture coords inside to prevent
1761 // overwriting them in case they are used as outputs of the texs instruction. 1787 // overwriting them in case they are used as outputs of the texs instruction.
1762 shader.AddLine("{"); 1788 shader.AddLine("{");
@@ -1778,20 +1804,65 @@ private:
1778 break; 1804 break;
1779 } 1805 }
1780 case OpCode::Id::TEXS: { 1806 case OpCode::Id::TEXS: {
1781 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1807 std::string coord;
1782 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 1808 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
1783 const std::string sampler = GetSampler(instr.sampler); 1809 bool is_array{instr.texs.IsArrayTexture()};
1784 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1810
1811 switch (texture_type) {
1812 case Tegra::Shader::TextureType::Texture2D: {
1813 if (is_array) {
1814 std::string index = regs.GetRegisterAsInteger(instr.gpr8);
1815 std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1816 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1817 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
1818 } else {
1819 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1820 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1821 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1822 }
1823 break;
1824 }
1825 default:
1826 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1827 static_cast<u32>(texture_type));
1828 UNREACHABLE();
1785 1829
1830 // Fallback to interpreting as a 2D texture for now
1831 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1832 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1833 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1834 texture_type = Tegra::Shader::TextureType::Texture2D;
1835 is_array = false;
1836 }
1837 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array);
1786 const std::string texture = "texture(" + sampler + ", coords)"; 1838 const std::string texture = "texture(" + sampler + ", coords)";
1787 WriteTexsInstruction(instr, coord, texture); 1839 WriteTexsInstruction(instr, coord, texture);
1788 break; 1840 break;
1789 } 1841 }
1790 case OpCode::Id::TLDS: { 1842 case OpCode::Id::TLDS: {
1791 const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); 1843 ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D);
1792 const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); 1844 ASSERT(instr.tlds.IsArrayTexture() == false);
1793 const std::string sampler = GetSampler(instr.sampler); 1845 std::string coord;
1794 const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; 1846
1847 switch (instr.tlds.GetTextureType()) {
1848 case Tegra::Shader::TextureType::Texture2D: {
1849 if (instr.tlds.IsArrayTexture()) {
1850 LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
1851 UNREACHABLE();
1852 } else {
1853 std::string x = regs.GetRegisterAsInteger(instr.gpr8);
1854 std::string y = regs.GetRegisterAsInteger(instr.gpr20);
1855 coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
1856 }
1857 break;
1858 }
1859 default:
1860 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1861 static_cast<u32>(instr.tlds.GetTextureType()));
1862 UNREACHABLE();
1863 }
1864 const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(),
1865 instr.tlds.IsArrayTexture());
1795 const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; 1866 const std::string texture = "texelFetch(" + sampler + ", coords, 0)";
1796 WriteTexsInstruction(instr, coord, texture); 1867 WriteTexsInstruction(instr, coord, texture);
1797 break; 1868 break;
@@ -1799,7 +1870,7 @@ private:
1799 case OpCode::Id::TLD4: { 1870 case OpCode::Id::TLD4: {
1800 ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D); 1871 ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D);
1801 ASSERT(instr.tld4.array == 0); 1872 ASSERT(instr.tld4.array == 0);
1802 std::string coord{}; 1873 std::string coord;
1803 1874
1804 switch (instr.tld4.texture_type) { 1875 switch (instr.tld4.texture_type) {
1805 case Tegra::Shader::TextureType::Texture2D: { 1876 case Tegra::Shader::TextureType::Texture2D: {
@@ -1814,7 +1885,8 @@ private:
1814 UNREACHABLE(); 1885 UNREACHABLE();
1815 } 1886 }
1816 1887
1817 const std::string sampler = GetSampler(instr.sampler); 1888 const std::string sampler =
1889 GetSampler(instr.sampler, instr.tld4.texture_type, false);
1818 // Add an extra scope and declare the texture coords inside to prevent 1890 // Add an extra scope and declare the texture coords inside to prevent
1819 // overwriting them in case they are used as outputs of the texs instruction. 1891 // overwriting them in case they are used as outputs of the texs instruction.
1820 shader.AddLine("{"); 1892 shader.AddLine("{");
@@ -1840,7 +1912,8 @@ private:
1840 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1912 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
1841 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 1913 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
1842 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 1914 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
1843 const std::string sampler = GetSampler(instr.sampler); 1915 const std::string sampler =
1916 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false);
1844 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1917 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
1845 const std::string texture = "textureGather(" + sampler + ", coords, " + 1918 const std::string texture = "textureGather(" + sampler + ", coords, " +
1846 std::to_string(instr.tld4s.component) + ')'; 1919 std::to_string(instr.tld4s.component) + ')';
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index cbb2090ea..a43e2997b 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -9,6 +9,7 @@
9#include <vector> 9#include <vector>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/shader_bytecode.h"
12 13
13namespace OpenGL::GLShader { 14namespace OpenGL::GLShader {
14 15
@@ -73,8 +74,9 @@ class SamplerEntry {
73 using Maxwell = Tegra::Engines::Maxwell3D::Regs; 74 using Maxwell = Tegra::Engines::Maxwell3D::Regs;
74 75
75public: 76public:
76 SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index) 77 SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index,
77 : offset(offset), stage(stage), sampler_index(index) {} 78 Tegra::Shader::TextureType type, bool is_array)
79 : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {}
78 80
79 size_t GetOffset() const { 81 size_t GetOffset() const {
80 return offset; 82 return offset;
@@ -89,8 +91,41 @@ public:
89 } 91 }
90 92
91 std::string GetName() const { 93 std::string GetName() const {
92 return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '[' + 94 return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '_' +
93 std::to_string(sampler_index) + ']'; 95 std::to_string(sampler_index);
96 }
97
98 std::string GetTypeString() const {
99 using Tegra::Shader::TextureType;
100 std::string glsl_type;
101
102 switch (type) {
103 case TextureType::Texture1D:
104 glsl_type = "sampler1D";
105 break;
106 case TextureType::Texture2D:
107 glsl_type = "sampler2D";
108 break;
109 case TextureType::Texture3D:
110 glsl_type = "sampler3D";
111 break;
112 case TextureType::TextureCube:
113 glsl_type = "samplerCube";
114 break;
115 default:
116 UNIMPLEMENTED();
117 }
118 if (is_array)
119 glsl_type += "Array";
120 return glsl_type;
121 }
122
123 Tegra::Shader::TextureType GetType() const {
124 return type;
125 }
126
127 bool IsArray() const {
128 return is_array;
94 } 129 }
95 130
96 u32 GetHash() const { 131 u32 GetHash() const {
@@ -105,11 +140,14 @@ private:
105 static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = { 140 static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = {
106 "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs", 141 "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs",
107 }; 142 };
143
108 /// Offset in TSC memory from which to read the sampler object, as specified by the sampling 144 /// Offset in TSC memory from which to read the sampler object, as specified by the sampling
109 /// instruction. 145 /// instruction.
110 size_t offset; 146 size_t offset;
111 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. 147 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used.
112 size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. 148 size_t sampler_index; ///< Value used to index into the generated GLSL sampler array.
149 Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc)
150 bool is_array; ///< Whether the texture is being sampled as an array texture or not.
113}; 151};
114 152
115struct ShaderEntries { 153struct ShaderEntries {
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 60a4defd1..6f70deb96 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -200,9 +200,9 @@ void OpenGLState::Apply() const {
200 const auto& texture_unit = texture_units[i]; 200 const auto& texture_unit = texture_units[i];
201 const auto& cur_state_texture_unit = cur_state.texture_units[i]; 201 const auto& cur_state_texture_unit = cur_state.texture_units[i];
202 202
203 if (texture_unit.texture_2d != cur_state_texture_unit.texture_2d) { 203 if (texture_unit.texture != cur_state_texture_unit.texture) {
204 glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); 204 glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum());
205 glBindTexture(GL_TEXTURE_2D, texture_unit.texture_2d); 205 glBindTexture(texture_unit.target, texture_unit.texture);
206 } 206 }
207 if (texture_unit.sampler != cur_state_texture_unit.sampler) { 207 if (texture_unit.sampler != cur_state_texture_unit.sampler) {
208 glBindSampler(static_cast<GLuint>(i), texture_unit.sampler); 208 glBindSampler(static_cast<GLuint>(i), texture_unit.sampler);
@@ -214,7 +214,7 @@ void OpenGLState::Apply() const {
214 texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) { 214 texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) {
215 std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g, 215 std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g,
216 texture_unit.swizzle.b, texture_unit.swizzle.a}; 216 texture_unit.swizzle.b, texture_unit.swizzle.a};
217 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); 217 glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
218 } 218 }
219 } 219 }
220 220
@@ -287,7 +287,7 @@ void OpenGLState::Apply() const {
287 287
288OpenGLState& OpenGLState::UnbindTexture(GLuint handle) { 288OpenGLState& OpenGLState::UnbindTexture(GLuint handle) {
289 for (auto& unit : texture_units) { 289 for (auto& unit : texture_units) {
290 if (unit.texture_2d == handle) { 290 if (unit.texture == handle) {
291 unit.Unbind(); 291 unit.Unbind();
292 } 292 }
293 } 293 }
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 46e96a97d..e3e24b9e7 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -94,8 +94,9 @@ public:
94 94
95 // 3 texture units - one for each that is used in PICA fragment shader emulation 95 // 3 texture units - one for each that is used in PICA fragment shader emulation
96 struct TextureUnit { 96 struct TextureUnit {
97 GLuint texture_2d; // GL_TEXTURE_BINDING_2D 97 GLuint texture; // GL_TEXTURE_BINDING_2D
98 GLuint sampler; // GL_SAMPLER_BINDING 98 GLuint sampler; // GL_SAMPLER_BINDING
99 GLenum target;
99 struct { 100 struct {
100 GLint r; // GL_TEXTURE_SWIZZLE_R 101 GLint r; // GL_TEXTURE_SWIZZLE_R
101 GLint g; // GL_TEXTURE_SWIZZLE_G 102 GLint g; // GL_TEXTURE_SWIZZLE_G
@@ -104,7 +105,7 @@ public:
104 } swizzle; 105 } swizzle;
105 106
106 void Unbind() { 107 void Unbind() {
107 texture_2d = 0; 108 texture = 0;
108 swizzle.r = GL_RED; 109 swizzle.r = GL_RED;
109 swizzle.g = GL_GREEN; 110 swizzle.g = GL_GREEN;
110 swizzle.b = GL_BLUE; 111 swizzle.b = GL_BLUE;
@@ -114,6 +115,7 @@ public:
114 void Reset() { 115 void Reset() {
115 Unbind(); 116 Unbind();
116 sampler = 0; 117 sampler = 0;
118 target = GL_TEXTURE_2D;
117 } 119 }
118 }; 120 };
119 std::array<TextureUnit, 32> texture_units; 121 std::array<TextureUnit, 32> texture_units;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 411a73d50..ccff3e342 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -177,7 +177,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
177 Memory::GetPointer(framebuffer_addr), 177 Memory::GetPointer(framebuffer_addr),
178 gl_framebuffer_data.data(), true); 178 gl_framebuffer_data.data(), true);
179 179
180 state.texture_units[0].texture_2d = screen_info.texture.resource.handle; 180 state.texture_units[0].texture = screen_info.texture.resource.handle;
181 state.Apply(); 181 state.Apply();
182 182
183 glActiveTexture(GL_TEXTURE0); 183 glActiveTexture(GL_TEXTURE0);
@@ -194,7 +194,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
194 194
195 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 195 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
196 196
197 state.texture_units[0].texture_2d = 0; 197 state.texture_units[0].texture = 0;
198 state.Apply(); 198 state.Apply();
199 } 199 }
200} 200}
@@ -205,7 +205,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
205 */ 205 */
206void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, 206void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
207 const TextureInfo& texture) { 207 const TextureInfo& texture) {
208 state.texture_units[0].texture_2d = texture.resource.handle; 208 state.texture_units[0].texture = texture.resource.handle;
209 state.Apply(); 209 state.Apply();
210 210
211 glActiveTexture(GL_TEXTURE0); 211 glActiveTexture(GL_TEXTURE0);
@@ -214,7 +214,7 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
214 // Update existing texture 214 // Update existing texture
215 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); 215 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
216 216
217 state.texture_units[0].texture_2d = 0; 217 state.texture_units[0].texture = 0;
218 state.Apply(); 218 state.Apply();
219} 219}
220 220
@@ -260,7 +260,7 @@ void RendererOpenGL::InitOpenGLObjects() {
260 // Allocation of storage is deferred until the first frame, when we 260 // Allocation of storage is deferred until the first frame, when we
261 // know the framebuffer size. 261 // know the framebuffer size.
262 262
263 state.texture_units[0].texture_2d = screen_info.texture.resource.handle; 263 state.texture_units[0].texture = screen_info.texture.resource.handle;
264 state.Apply(); 264 state.Apply();
265 265
266 glActiveTexture(GL_TEXTURE0); 266 glActiveTexture(GL_TEXTURE0);
@@ -272,7 +272,7 @@ void RendererOpenGL::InitOpenGLObjects() {
272 272
273 screen_info.display_texture = screen_info.texture.resource.handle; 273 screen_info.display_texture = screen_info.texture.resource.handle;
274 274
275 state.texture_units[0].texture_2d = 0; 275 state.texture_units[0].texture = 0;
276 state.Apply(); 276 state.Apply();
277 277
278 // Clear screen to black 278 // Clear screen to black
@@ -305,14 +305,14 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
305 UNREACHABLE(); 305 UNREACHABLE();
306 } 306 }
307 307
308 state.texture_units[0].texture_2d = texture.resource.handle; 308 state.texture_units[0].texture = texture.resource.handle;
309 state.Apply(); 309 state.Apply();
310 310
311 glActiveTexture(GL_TEXTURE0); 311 glActiveTexture(GL_TEXTURE0);
312 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, 312 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
313 texture.gl_format, texture.gl_type, nullptr); 313 texture.gl_format, texture.gl_type, nullptr);
314 314
315 state.texture_units[0].texture_2d = 0; 315 state.texture_units[0].texture = 0;
316 state.Apply(); 316 state.Apply();
317} 317}
318 318
@@ -354,14 +354,14 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
354 ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), 354 ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v),
355 }}; 355 }};
356 356
357 state.texture_units[0].texture_2d = screen_info.display_texture; 357 state.texture_units[0].texture = screen_info.display_texture;
358 state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; 358 state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
359 state.Apply(); 359 state.Apply();
360 360
361 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); 361 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
362 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 362 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
363 363
364 state.texture_units[0].texture_2d = 0; 364 state.texture_units[0].texture = 0;
365 state.Apply(); 365 state.Apply();
366} 366}
367 367
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index c6bd2f4b9..c2fb824b2 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -170,8 +170,12 @@ struct TICEntry {
170 BitField<0, 16, u32> width_minus_1; 170 BitField<0, 16, u32> width_minus_1;
171 BitField<23, 4, TextureType> texture_type; 171 BitField<23, 4, TextureType> texture_type;
172 }; 172 };
173 u16 height_minus_1; 173 union {
174 INSERT_PADDING_BYTES(10); 174 BitField<0, 16, u32> height_minus_1;
175 BitField<16, 15, u32> depth_minus_1;
176 };
177
178 INSERT_PADDING_BYTES(8);
175 179
176 GPUVAddr Address() const { 180 GPUVAddr Address() const {
177 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); 181 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
@@ -192,6 +196,10 @@ struct TICEntry {
192 return height_minus_1 + 1; 196 return height_minus_1 + 1;
193 } 197 }
194 198
199 u32 Depth() const {
200 return depth_minus_1 + 1;
201 }
202
195 u32 BlockHeight() const { 203 u32 BlockHeight() const {
196 ASSERT(header_version == TICHeaderVersion::BlockLinear || 204 ASSERT(header_version == TICHeaderVersion::BlockLinear ||
197 header_version == TICHeaderVersion::BlockLinearColorKey); 205 header_version == TICHeaderVersion::BlockLinearColorKey);