summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-07 18:46:16 -0400
committerGravatar GitHub2018-04-07 18:46:16 -0400
commit227bc78cbefef0866fc39db1383ea4f012583e11 (patch)
tree4b6979d7483cf98463afa394d2e11001e91aa195 /src
parentMerge pull request #315 from jroweboy/spelling-fix (diff)
parentFix clang format issues (diff)
downloadyuzu-227bc78cbefef0866fc39db1383ea4f012583e11.tar.gz
yuzu-227bc78cbefef0866fc39db1383ea4f012583e11.tar.xz
yuzu-227bc78cbefef0866fc39db1383ea4f012583e11.zip
Merge pull request #314 from jroweboy/tegra-progress-3b
GPU: Bind uploaded textures when drawing (Rebased)
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp94
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h24
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp188
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h89
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_state.h2
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h23
-rw-r--r--src/video_core/textures/texture.h23
9 files changed, 274 insertions, 173 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 124753032..2d7c3152f 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -231,6 +231,8 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
231 231
232 // TODO(Subv): Different data types for separate components are not supported 232 // TODO(Subv): Different data types for separate components are not supported
233 ASSERT(r_type == g_type && r_type == b_type && r_type == a_type); 233 ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
234 // TODO(Subv): Only UNORM formats are supported for now.
235 ASSERT(r_type == Texture::ComponentType::UNORM);
234 236
235 return tic_entry; 237 return tic_entry;
236} 238}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 911890f16..f217a265b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -66,6 +66,12 @@ RasterizerOpenGL::RasterizerOpenGL() {
66 has_ARB_separate_shader_objects = false; 66 has_ARB_separate_shader_objects = false;
67 has_ARB_vertex_attrib_binding = false; 67 has_ARB_vertex_attrib_binding = false;
68 68
69 // Create sampler objects
70 for (size_t i = 0; i < texture_samplers.size(); ++i) {
71 texture_samplers[i].Create();
72 state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
73 }
74
69 GLint ext_num; 75 GLint ext_num;
70 glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); 76 glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num);
71 for (GLint i = 0; i < ext_num; i++) { 77 for (GLint i = 0; i < ext_num; i++) {
@@ -270,7 +276,9 @@ void RasterizerOpenGL::DrawArrays() {
270 276
271 // TODO(bunnei): Sync framebuffer_scale uniform here 277 // TODO(bunnei): Sync framebuffer_scale uniform here
272 // TODO(bunnei): Sync scissorbox uniform(s) here 278 // TODO(bunnei): Sync scissorbox uniform(s) here
273 // TODO(bunnei): Sync and bind the texture surfaces 279
280 // Sync and bind the texture surfaces
281 BindTextures();
274 282
275 // Sync and bind the shader 283 // Sync and bind the shader
276 if (shader_dirty) { 284 if (shader_dirty) {
@@ -374,6 +382,39 @@ void RasterizerOpenGL::DrawArrays() {
374 } 382 }
375} 383}
376 384
385void RasterizerOpenGL::BindTextures() {
386 using Regs = Tegra::Engines::Maxwell3D::Regs;
387 auto maxwell3d = Core::System::GetInstance().GPU().Get3DEngine();
388
389 // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a
390 // certain number in OpenGL. We try to only use the minimum amount of host textures by not
391 // keeping a 1:1 relation between guest texture ids and host texture ids, ie, guest texture id 8
392 // can be host texture id 0 if it's the only texture used in the guest shader program.
393 u32 host_texture_index = 0;
394 for (u32 stage = 0; stage < Regs::MaxShaderStage; ++stage) {
395 ASSERT(host_texture_index < texture_samplers.size());
396 const auto textures = maxwell3d.GetStageTextures(static_cast<Regs::ShaderStage>(stage));
397 for (unsigned texture_index = 0; texture_index < textures.size(); ++texture_index) {
398 const auto& texture = textures[texture_index];
399
400 if (texture.enabled) {
401 texture_samplers[host_texture_index].SyncWithConfig(texture.tsc);
402 Surface surface = res_cache.GetTextureSurface(texture);
403 if (surface != nullptr) {
404 state.texture_units[host_texture_index].texture_2d = surface->texture.handle;
405 } else {
406 // Can occur when texture addr is null or its memory is unmapped/invalid
407 state.texture_units[texture_index].texture_2d = 0;
408 }
409
410 ++host_texture_index;
411 } else {
412 state.texture_units[texture_index].texture_2d = 0;
413 }
414 }
415 }
416}
417
377void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {} 418void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {}
378 419
379void RasterizerOpenGL::FlushAll() { 420void RasterizerOpenGL::FlushAll() {
@@ -452,6 +493,44 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
452 return true; 493 return true;
453} 494}
454 495
496void RasterizerOpenGL::SamplerInfo::Create() {
497 sampler.Create();
498 mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear;
499 wrap_u = wrap_v = Tegra::Texture::WrapMode::Wrap;
500 border_color_r = border_color_g = border_color_b = border_color_a = 0;
501
502 // default is GL_LINEAR_MIPMAP_LINEAR
503 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
504 // Other attributes have correct defaults
505}
506
507void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
508 GLuint s = sampler.handle;
509
510 if (mag_filter != config.mag_filter) {
511 mag_filter = config.mag_filter;
512 glSamplerParameteri(s, GL_TEXTURE_MAG_FILTER, MaxwellToGL::TextureFilterMode(mag_filter));
513 }
514 if (min_filter != config.min_filter) {
515 min_filter = config.min_filter;
516 glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, MaxwellToGL::TextureFilterMode(min_filter));
517 }
518
519 if (wrap_u != config.wrap_u) {
520 wrap_u = config.wrap_u;
521 glSamplerParameteri(s, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(wrap_u));
522 }
523 if (wrap_v != config.wrap_v) {
524 wrap_v = config.wrap_v;
525 glSamplerParameteri(s, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(wrap_v));
526 }
527
528 if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border) {
529 // TODO(Subv): Implement border color
530 ASSERT(false);
531 }
532}
533
455void RasterizerOpenGL::SetShader() { 534void RasterizerOpenGL::SetShader() {
456 // TODO(bunnei): The below sets up a static test shader for passing untransformed vertices to 535 // TODO(bunnei): The below sets up a static test shader for passing untransformed vertices to
457 // OpenGL for rendering. This should be removed/replaced when we start emulating Maxwell 536 // OpenGL for rendering. This should be removed/replaced when we start emulating Maxwell
@@ -479,10 +558,10 @@ void main() {
479in vec2 frag_tex_coord; 558in vec2 frag_tex_coord;
480out vec4 color; 559out vec4 color;
481 560
482uniform sampler2D color_texture; 561uniform sampler2D tex[32];
483 562
484void main() { 563void main() {
485 color = vec4(1.0, 0.0, 1.0, 0.0); 564 color = texture(tex[0], frag_tex_coord);
486} 565}
487)"; 566)";
488 567
@@ -503,6 +582,15 @@ void main() {
503 state.draw.shader_program = test_shader.shader.handle; 582 state.draw.shader_program = test_shader.shader.handle;
504 state.Apply(); 583 state.Apply();
505 584
585 for (u32 texture = 0; texture < texture_samplers.size(); ++texture) {
586 // Set the texture samplers to correspond to different texture units
587 std::string uniform_name = "tex[" + std::to_string(texture) + "]";
588 GLint uniform_tex = glGetUniformLocation(test_shader.shader.handle, uniform_name.c_str());
589 if (uniform_tex != -1) {
590 glUniform1i(uniform_tex, TextureUnits::MaxwellTexture(texture).id);
591 }
592 }
593
506 if (has_ARB_separate_shader_objects) { 594 if (has_ARB_separate_shader_objects) {
507 state.draw.shader_program = 0; 595 state.draw.shader_program = 0;
508 state.Apply(); 596 state.Apply();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index fd53e94cd..d868bf421 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -85,12 +85,34 @@ public:
85 "FSUniformData structure must be less than 16kb as per the OpenGL spec"); 85 "FSUniformData structure must be less than 16kb as per the OpenGL spec");
86 86
87private: 87private:
88 struct SamplerInfo {}; 88 class SamplerInfo {
89 public:
90 OGLSampler sampler;
91
92 /// Creates the sampler object, initializing its state so that it's in sync with the
93 /// SamplerInfo struct.
94 void Create();
95 /// Syncs the sampler object with the config, updating any necessary state.
96 void SyncWithConfig(const Tegra::Texture::TSCEntry& config);
97
98 private:
99 Tegra::Texture::TextureFilter mag_filter;
100 Tegra::Texture::TextureFilter min_filter;
101 Tegra::Texture::WrapMode wrap_u;
102 Tegra::Texture::WrapMode wrap_v;
103 u32 border_color_r;
104 u32 border_color_g;
105 u32 border_color_b;
106 u32 border_color_a;
107 };
89 108
90 /// Binds the framebuffer color and depth surface 109 /// Binds the framebuffer color and depth surface
91 void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, 110 void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
92 bool has_stencil); 111 bool has_stencil);
93 112
113 /// Binds the required textures to OpenGL before drawing a batch.
114 void BindTextures();
115
94 /// Syncs the viewport to match the guest state 116 /// Syncs the viewport to match the guest state
95 void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); 117 void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);
96 118
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 4fd7cdf6a..5cbafa2e7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -30,6 +30,7 @@
30#include "video_core/engines/maxwell_3d.h" 30#include "video_core/engines/maxwell_3d.h"
31#include "video_core/renderer_opengl/gl_rasterizer_cache.h" 31#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
32#include "video_core/renderer_opengl/gl_state.h" 32#include "video_core/renderer_opengl/gl_state.h"
33#include "video_core/textures/decoders.h"
33#include "video_core/utils.h" 34#include "video_core/utils.h"
34#include "video_core/video_core.h" 35#include "video_core/video_core.h"
35 36
@@ -40,36 +41,36 @@ struct FormatTuple {
40 GLint internal_format; 41 GLint internal_format;
41 GLenum format; 42 GLenum format;
42 GLenum type; 43 GLenum type;
44 bool compressed;
45 // How many pixels in the original texture are equivalent to one pixel in the compressed
46 // texture.
47 u32 compression_factor;
43}; 48};
44 49
45static constexpr std::array<FormatTuple, 5> fb_format_tuples = {{ 50static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{
46 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}, // RGBA8 51 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8
47 {GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE}, // RGB8
48 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, // RGB5A1
49 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // RGB565
50 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, // RGBA4
51}}; 52}};
52 53
53static constexpr std::array<FormatTuple, 4> depth_format_tuples = {{ 54static constexpr std::array<FormatTuple, 2> tex_format_tuples = {{
54 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16 55 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8
55 {}, 56 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
56 {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, // D24
57 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24S8
58}}; 57}};
59 58
60static constexpr FormatTuple tex_tuple = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
61
62static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { 59static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
63 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); 60 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
64 if (type == SurfaceType::Color) { 61 if (type == SurfaceType::Color) {
65 ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size()); 62 ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size());
66 return fb_format_tuples[static_cast<unsigned int>(pixel_format)]; 63 return fb_format_tuples[static_cast<unsigned int>(pixel_format)];
67 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { 64 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
68 size_t tuple_idx = static_cast<size_t>(pixel_format) - 14; 65 // TODO(Subv): Implement depth formats
69 ASSERT(tuple_idx < depth_format_tuples.size()); 66 ASSERT_MSG(false, "Unimplemented");
70 return depth_format_tuples[tuple_idx]; 67 } else if (type == SurfaceType::Texture) {
68 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
69 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
71 } 70 }
72 return tex_tuple; 71
72 UNREACHABLE();
73 return {};
73} 74}
74 75
75template <typename Map, typename Interval> 76template <typename Map, typename Interval>
@@ -92,26 +93,16 @@ static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) {
92 u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel; 93 u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel;
93 u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel; 94 u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel;
94 if (morton_to_gl) { 95 if (morton_to_gl) {
95 if (format == PixelFormat::D24S8) { 96 std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel);
96 gl_ptr[0] = tile_ptr[3];
97 std::memcpy(gl_ptr + 1, tile_ptr, 3);
98 } else {
99 std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel);
100 }
101 } else { 97 } else {
102 if (format == PixelFormat::D24S8) { 98 std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel);
103 std::memcpy(tile_ptr, gl_ptr + 1, 3);
104 tile_ptr[3] = gl_ptr[0];
105 } else {
106 std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel);
107 }
108 } 99 }
109 } 100 }
110 } 101 }
111} 102}
112 103
113template <bool morton_to_gl, PixelFormat format> 104template <bool morton_to_gl, PixelFormat format>
114static void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) { 105void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) {
115 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 106 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
116 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 107 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
117 108
@@ -122,46 +113,28 @@ static void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr
122 Memory::GetPointer(base), gl_buffer, morton_to_gl); 113 Memory::GetPointer(base), gl_buffer, morton_to_gl);
123} 114}
124 115
125static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 18> morton_to_gl_fns = { 116template <>
117void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base,
118 VAddr start, VAddr end) {
119 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8;
120 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1);
121
122 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the
123 // configuration for this and perform more generic un/swizzle
124 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
125 auto data =
126 Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height);
127 std::memcpy(gl_buffer, data.data(), data.size());
128}
129
130static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = {
126 MortonCopy<true, PixelFormat::RGBA8>, 131 MortonCopy<true, PixelFormat::RGBA8>,
127 nullptr, 132 MortonCopy<true, PixelFormat::DXT1>,
128 nullptr,
129 nullptr,
130 nullptr,
131 nullptr,
132 nullptr,
133 nullptr,
134 nullptr,
135 nullptr,
136 nullptr,
137 nullptr,
138 nullptr,
139 nullptr,
140 nullptr,
141 nullptr,
142 nullptr,
143 nullptr,
144}; 133};
145 134
146static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 18> gl_to_morton_fns = { 135static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = {
147 MortonCopy<false, PixelFormat::RGBA8>, 136 MortonCopy<false, PixelFormat::RGBA8>,
148 nullptr, 137 MortonCopy<false, PixelFormat::DXT1>,
149 nullptr,
150 nullptr,
151 nullptr,
152 nullptr,
153 nullptr,
154 nullptr,
155 nullptr,
156 nullptr,
157 nullptr,
158 nullptr,
159 nullptr,
160 nullptr,
161 nullptr,
162 nullptr,
163 nullptr,
164 nullptr,
165}; 138};
166 139
167// Allocate an uninitialized texture of appropriate size and format for the surface 140// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -175,8 +148,11 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup
175 cur_state.Apply(); 148 cur_state.Apply();
176 glActiveTexture(GL_TEXTURE0); 149 glActiveTexture(GL_TEXTURE0);
177 150
178 glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0, 151 if (!format_tuple.compressed) {
179 format_tuple.format, format_tuple.type, nullptr); 152 // Only pre-create the texture for non-compressed textures.
153 glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
154 format_tuple.format, format_tuple.type, nullptr);
155 }
180 156
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 157 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 158 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -606,9 +582,18 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
606 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(stride)); 582 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(stride));
607 583
608 glActiveTexture(GL_TEXTURE0); 584 glActiveTexture(GL_TEXTURE0);
609 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()), 585 if (tuple.compressed) {
610 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, 586 glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
611 &gl_buffer[buffer_offset]); 587 static_cast<GLsizei>(rect.GetWidth()),
588 static_cast<GLsizei>(rect.GetHeight()), 0,
589 rect.GetWidth() * rect.GetHeight() *
590 GetGLBytesPerPixel(pixel_format) / tuple.compression_factor,
591 &gl_buffer[buffer_offset]);
592 } else {
593 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
594 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
595 &gl_buffer[buffer_offset]);
596 }
612 597
613 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 598 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
614 599
@@ -954,15 +939,6 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
954 if (expandable != nullptr && expandable->res_scale > target_res_scale) { 939 if (expandable != nullptr && expandable->res_scale > target_res_scale) {
955 target_res_scale = expandable->res_scale; 940 target_res_scale = expandable->res_scale;
956 } 941 }
957 // Keep res_scale when reinterpreting d24s8 -> rgba8
958 if (params.pixel_format == PixelFormat::RGBA8) {
959 find_params.pixel_format = PixelFormat::D24S8;
960 expandable = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(
961 surface_cache, find_params, match_res_scale);
962 if (expandable != nullptr && expandable->res_scale > target_res_scale) {
963 target_res_scale = expandable->res_scale;
964 }
965 }
966 } 942 }
967 SurfaceParams new_params = params; 943 SurfaceParams new_params = params;
968 new_params.res_scale = target_res_scale; 944 new_params.res_scale = target_res_scale;
@@ -1056,9 +1032,34 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams&
1056 return std::make_tuple(surface, surface->GetScaledSubRect(params)); 1032 return std::make_tuple(surface, surface->GetScaledSubRect(params));
1057} 1033}
1058 1034
1059Surface RasterizerCacheOpenGL::GetTextureSurface(const void* config) { 1035Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
1060 UNREACHABLE(); 1036 auto& gpu = Core::System::GetInstance().GPU();
1061 return {}; 1037
1038 SurfaceParams params;
1039 params.addr = gpu.memory_manager->PhysicalToVirtualAddress(config.tic.Address());
1040 params.width = config.tic.Width();
1041 params.height = config.tic.Height();
1042 params.is_tiled = config.tic.IsTiled();
1043 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
1044 params.UpdateParams();
1045
1046 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) {
1047 Surface src_surface;
1048 MathUtil::Rectangle<u32> rect;
1049 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
1050
1051 params.res_scale = src_surface->res_scale;
1052 Surface tmp_surface = CreateSurface(params);
1053 BlitTextures(src_surface->texture.handle, rect, tmp_surface->texture.handle,
1054 tmp_surface->GetScaledRect(),
1055 SurfaceParams::GetFormatType(params.pixel_format), read_framebuffer.handle,
1056 draw_framebuffer.handle);
1057
1058 remove_surfaces.emplace(tmp_surface);
1059 return tmp_surface;
1060 }
1061
1062 return GetSurface(params, ScaleMatch::Ignore, true);
1062} 1063}
1063 1064
1064SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( 1065SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
@@ -1240,27 +1241,6 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr,
1240 continue; 1241 continue;
1241 } 1242 }
1242 1243
1243 // D24S8 to RGBA8
1244 if (surface->pixel_format == PixelFormat::RGBA8) {
1245 params.pixel_format = PixelFormat::D24S8;
1246 Surface reinterpret_surface =
1247 FindMatch<MatchFlags::Copy>(surface_cache, params, ScaleMatch::Ignore, interval);
1248 if (reinterpret_surface != nullptr) {
1249 ASSERT(reinterpret_surface->pixel_format == PixelFormat::D24S8);
1250
1251 SurfaceInterval convert_interval = params.GetCopyableInterval(reinterpret_surface);
1252 SurfaceParams convert_params = surface->FromInterval(convert_interval);
1253 auto src_rect = reinterpret_surface->GetScaledSubRect(convert_params);
1254 auto dest_rect = surface->GetScaledSubRect(convert_params);
1255
1256 ConvertD24S8toABGR(reinterpret_surface->texture.handle, src_rect,
1257 surface->texture.handle, dest_rect);
1258
1259 surface->invalid_regions.erase(convert_interval);
1260 continue;
1261 }
1262 }
1263
1264 // Load data from Switch memory 1244 // Load data from Switch memory
1265 FlushRegion(params.addr, params.size); 1245 FlushRegion(params.addr, params.size);
1266 surface->LoadGLBuffer(params.addr, params.end); 1246 surface->LoadGLBuffer(params.addr, params.end);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 37b1dae80..06524fc59 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -24,6 +24,7 @@
24#include "common/math_util.h" 24#include "common/math_util.h"
25#include "video_core/gpu.h" 25#include "video_core/gpu.h"
26#include "video_core/renderer_opengl/gl_resource_manager.h" 26#include "video_core/renderer_opengl/gl_resource_manager.h"
27#include "video_core/textures/texture.h"
27 28
28struct CachedSurface; 29struct CachedSurface;
29using Surface = std::shared_ptr<CachedSurface>; 30using Surface = std::shared_ptr<CachedSurface>;
@@ -51,30 +52,8 @@ enum class ScaleMatch {
51 52
52struct SurfaceParams { 53struct SurfaceParams {
53 enum class PixelFormat { 54 enum class PixelFormat {
54 // First 5 formats are shared between textures and color buffers
55 RGBA8 = 0, 55 RGBA8 = 0,
56 RGB8 = 1, 56 DXT1 = 1,
57 RGB5A1 = 2,
58 RGB565 = 3,
59 RGBA4 = 4,
60
61 // Texture-only formats
62 IA8 = 5,
63 RG8 = 6,
64 I8 = 7,
65 A8 = 8,
66 IA4 = 9,
67 I4 = 10,
68 A4 = 11,
69 ETC1 = 12,
70 ETC1A4 = 13,
71
72 // Depth buffer-only formats
73 D16 = 14,
74 // gap
75 D24 = 16,
76 D24S8 = 17,
77
78 Invalid = 255, 57 Invalid = 255,
79 }; 58 };
80 59
@@ -88,28 +67,15 @@ struct SurfaceParams {
88 }; 67 };
89 68
90 static constexpr unsigned int GetFormatBpp(PixelFormat format) { 69 static constexpr unsigned int GetFormatBpp(PixelFormat format) {
91 constexpr std::array<unsigned int, 18> bpp_table = { 70 if (format == PixelFormat::Invalid)
71 return 0;
72
73 constexpr std::array<unsigned int, 2> bpp_table = {
92 32, // RGBA8 74 32, // RGBA8
93 24, // RGB8 75 64, // DXT1
94 16, // RGB5A1
95 16, // RGB565
96 16, // RGBA4
97 16, // IA8
98 16, // RG8
99 8, // I8
100 8, // A8
101 8, // IA4
102 4, // I4
103 4, // A4
104 4, // ETC1
105 8, // ETC1A4
106 16, // D16
107 0,
108 24, // D24
109 32, // D24S8
110 }; 76 };
111 77
112 assert(static_cast<size_t>(format) < bpp_table.size()); 78 ASSERT(static_cast<size_t>(format) < bpp_table.size());
113 return bpp_table[static_cast<size_t>(format)]; 79 return bpp_table[static_cast<size_t>(format)];
114 } 80 }
115 unsigned int GetFormatBpp() const { 81 unsigned int GetFormatBpp() const {
@@ -134,6 +100,18 @@ struct SurfaceParams {
134 } 100 }
135 } 101 }
136 102
103 static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format) {
104 // TODO(Subv): Properly implement this
105 switch (format) {
106 case Tegra::Texture::TextureFormat::A8R8G8B8:
107 return PixelFormat::RGBA8;
108 case Tegra::Texture::TextureFormat::DXT1:
109 return PixelFormat::DXT1;
110 default:
111 UNREACHABLE();
112 }
113 }
114
137 static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) { 115 static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) {
138 SurfaceType a_type = GetFormatType(pixel_format_a); 116 SurfaceType a_type = GetFormatType(pixel_format_a);
139 SurfaceType b_type = GetFormatType(pixel_format_b); 117 SurfaceType b_type = GetFormatType(pixel_format_b);
@@ -154,22 +132,17 @@ struct SurfaceParams {
154 return false; 132 return false;
155 } 133 }
156 134
157 static constexpr SurfaceType GetFormatType(PixelFormat pixel_format) { 135 static SurfaceType GetFormatType(PixelFormat pixel_format) {
158 if ((unsigned int)pixel_format < 5) { 136 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::RGBA8)) {
159 return SurfaceType::Color; 137 return SurfaceType::Color;
160 } 138 }
161 139
162 if ((unsigned int)pixel_format < 14) { 140 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::DXT1)) {
163 return SurfaceType::Texture; 141 return SurfaceType::Texture;
164 } 142 }
165 143
166 if (pixel_format == PixelFormat::D16 || pixel_format == PixelFormat::D24) { 144 // TODO(Subv): Implement the other formats
167 return SurfaceType::Depth; 145 ASSERT(false);
168 }
169
170 if (pixel_format == PixelFormat::D24S8) {
171 return SurfaceType::DepthStencil;
172 }
173 146
174 return SurfaceType::Invalid; 147 return SurfaceType::Invalid;
175 } 148 }
@@ -265,12 +238,10 @@ struct CachedSurface : SurfaceParams {
265 OGLTexture texture; 238 OGLTexture texture;
266 239
267 static constexpr unsigned int GetGLBytesPerPixel(PixelFormat format) { 240 static constexpr unsigned int GetGLBytesPerPixel(PixelFormat format) {
268 // OpenGL needs 4 bpp alignment for D24 since using GL_UNSIGNED_INT as type 241 if (format == PixelFormat::Invalid)
269 return format == PixelFormat::Invalid 242 return 0;
270 ? 0 243
271 : (format == PixelFormat::D24 || GetFormatType(format) == SurfaceType::Texture) 244 return SurfaceParams::GetFormatBpp(format) / 8;
272 ? 4
273 : SurfaceParams::GetFormatBpp(format) / 8;
274 } 245 }
275 246
276 std::unique_ptr<u8[]> gl_buffer; 247 std::unique_ptr<u8[]> gl_buffer;
@@ -313,7 +284,7 @@ public:
313 bool load_if_create); 284 bool load_if_create);
314 285
315 /// Get a surface based on the texture configuration 286 /// Get a surface based on the texture configuration
316 Surface GetTextureSurface(const void* config); 287 Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config);
317 288
318 /// Get the color and depth surfaces based on the framebuffer configuration 289 /// Get the color and depth surfaces based on the framebuffer configuration
319 SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, 290 SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 1d396728b..6da3a7781 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -194,7 +194,7 @@ void OpenGLState::Apply() const {
194 // Textures 194 // Textures
195 for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { 195 for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
196 if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { 196 if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) {
197 glActiveTexture(TextureUnits::PicaTexture(i).Enum()); 197 glActiveTexture(TextureUnits::MaxwellTexture(i).Enum());
198 glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); 198 glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d);
199 } 199 }
200 if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { 200 if (texture_units[i].sampler != cur_state.texture_units[i].sampler) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index c1f4efc8c..b18af14bb 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -16,7 +16,7 @@ struct TextureUnit {
16 } 16 }
17}; 17};
18 18
19constexpr TextureUnit PicaTexture(int unit) { 19constexpr TextureUnit MaxwellTexture(int unit) {
20 return TextureUnit{unit}; 20 return TextureUnit{unit};
21} 21}
22 22
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index d847317ac..48ee80125 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -47,4 +47,27 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
47 return {}; 47 return {};
48} 48}
49 49
50inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) {
51 switch (filter_mode) {
52 case Tegra::Texture::TextureFilter::Linear:
53 return GL_LINEAR;
54 case Tegra::Texture::TextureFilter::Nearest:
55 return GL_NEAREST;
56 }
57 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode=%u",
58 static_cast<u32>(filter_mode));
59 UNREACHABLE();
60 return {};
61}
62
63inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
64 switch (wrap_mode) {
65 case Tegra::Texture::WrapMode::ClampToEdge:
66 return GL_CLAMP_TO_EDGE;
67 }
68 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode=%u", static_cast<u32>(wrap_mode));
69 UNREACHABLE();
70 return {};
71}
72
50} // namespace MaxwellToGL 73} // namespace MaxwellToGL
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 07936f8a3..c12ed6e1d 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -37,6 +37,16 @@ enum class TICHeaderVersion : u32 {
37 BlockLinearColorKey = 4, 37 BlockLinearColorKey = 4,
38}; 38};
39 39
40enum class ComponentType : u32 {
41 SNORM = 1,
42 UNORM = 2,
43 SINT = 3,
44 UINT = 4,
45 SNORM_FORCE_FP16 = 5,
46 UNORM_FORCE_FP16 = 6,
47 FLOAT = 7
48};
49
40union TextureHandle { 50union TextureHandle {
41 u32 raw; 51 u32 raw;
42 BitField<0, 20, u32> tic_id; 52 BitField<0, 20, u32> tic_id;
@@ -48,10 +58,10 @@ struct TICEntry {
48 union { 58 union {
49 u32 raw; 59 u32 raw;
50 BitField<0, 7, TextureFormat> format; 60 BitField<0, 7, TextureFormat> format;
51 BitField<7, 3, u32> r_type; 61 BitField<7, 3, ComponentType> r_type;
52 BitField<10, 3, u32> g_type; 62 BitField<10, 3, ComponentType> g_type;
53 BitField<13, 3, u32> b_type; 63 BitField<13, 3, ComponentType> b_type;
54 BitField<16, 3, u32> a_type; 64 BitField<16, 3, ComponentType> a_type;
55 }; 65 };
56 u32 address_low; 66 u32 address_low;
57 union { 67 union {
@@ -77,6 +87,11 @@ struct TICEntry {
77 u32 Height() const { 87 u32 Height() const {
78 return height_minus_1 + 1; 88 return height_minus_1 + 1;
79 } 89 }
90
91 bool IsTiled() const {
92 return header_version == TICHeaderVersion::BlockLinear ||
93 header_version == TICHeaderVersion::BlockLinearColorKey;
94 }
80}; 95};
81static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); 96static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size");
82 97