diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 166 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 117 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 5 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.h | 3 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 25 |
11 files changed, 260 insertions, 118 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index a2f162602..2a3ff234a 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -218,8 +218,9 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const { | |||
| 218 | Texture::TICEntry tic_entry; | 218 | Texture::TICEntry tic_entry; |
| 219 | Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); | 219 | Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); |
| 220 | 220 | ||
| 221 | ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear, | 221 | ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear || |
| 222 | "TIC versions other than BlockLinear are unimplemented"); | 222 | tic_entry.header_version == Texture::TICHeaderVersion::Pitch, |
| 223 | "TIC versions other than BlockLinear or Pitch are unimplemented"); | ||
| 223 | 224 | ||
| 224 | ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) || | 225 | ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) || |
| 225 | (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap), | 226 | (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap), |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index b379d8057..d4fcedace 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -319,7 +319,15 @@ public: | |||
| 319 | } | 319 | } |
| 320 | } rt[NumRenderTargets]; | 320 | } rt[NumRenderTargets]; |
| 321 | 321 | ||
| 322 | INSERT_PADDING_WORDS(0x80); | 322 | struct { |
| 323 | f32 scale_x; | ||
| 324 | f32 scale_y; | ||
| 325 | f32 scale_z; | ||
| 326 | u32 translate_x; | ||
| 327 | u32 translate_y; | ||
| 328 | u32 translate_z; | ||
| 329 | INSERT_PADDING_WORDS(2); | ||
| 330 | } viewport_transform[NumViewports]; | ||
| 323 | 331 | ||
| 324 | struct { | 332 | struct { |
| 325 | union { | 333 | union { |
| @@ -649,6 +657,7 @@ private: | |||
| 649 | "Field " #field_name " has invalid position") | 657 | "Field " #field_name " has invalid position") |
| 650 | 658 | ||
| 651 | ASSERT_REG_POSITION(rt, 0x200); | 659 | ASSERT_REG_POSITION(rt, 0x200); |
| 660 | ASSERT_REG_POSITION(viewport_transform[0], 0x280); | ||
| 652 | ASSERT_REG_POSITION(viewport, 0x300); | 661 | ASSERT_REG_POSITION(viewport, 0x300); |
| 653 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); | 662 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); |
| 654 | ASSERT_REG_POSITION(zeta, 0x3F8); | 663 | ASSERT_REG_POSITION(zeta, 0x3F8); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7b6240e65..13e2a77ce 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -523,9 +523,12 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu | |||
| 523 | src_params.width = std::min(framebuffer.width, pixel_stride); | 523 | src_params.width = std::min(framebuffer.width, pixel_stride); |
| 524 | src_params.height = framebuffer.height; | 524 | src_params.height = framebuffer.height; |
| 525 | src_params.stride = pixel_stride; | 525 | src_params.stride = pixel_stride; |
| 526 | src_params.is_tiled = false; | 526 | src_params.is_tiled = true; |
| 527 | src_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; | ||
| 527 | src_params.pixel_format = | 528 | src_params.pixel_format = |
| 528 | SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); | 529 | SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); |
| 530 | src_params.component_type = | ||
| 531 | SurfaceParams::ComponentTypeFromGPUPixelFormat(framebuffer.pixel_format); | ||
| 529 | src_params.UpdateParams(); | 532 | src_params.UpdateParams(); |
| 530 | 533 | ||
| 531 | MathUtil::Rectangle<u32> src_rect; | 534 | MathUtil::Rectangle<u32> src_rect; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 213b20a21..561c6913d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | using SurfaceType = SurfaceParams::SurfaceType; | 37 | using SurfaceType = SurfaceParams::SurfaceType; |
| 38 | using PixelFormat = SurfaceParams::PixelFormat; | 38 | using PixelFormat = SurfaceParams::PixelFormat; |
| 39 | using ComponentType = SurfaceParams::ComponentType; | ||
| 39 | 40 | ||
| 40 | struct FormatTuple { | 41 | struct FormatTuple { |
| 41 | GLint internal_format; | 42 | GLint internal_format; |
| @@ -47,26 +48,24 @@ struct FormatTuple { | |||
| 47 | u32 compression_factor; | 48 | u32 compression_factor; |
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 50 | static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{ | 51 | static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{ |
| 51 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 | 52 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8 |
| 53 | {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1}, // B5G6R5 | ||
| 54 | {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 | ||
| 55 | {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23 | ||
| 56 | {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45 | ||
| 52 | }}; | 57 | }}; |
| 53 | 58 | ||
| 54 | static constexpr std::array<FormatTuple, 2> tex_format_tuples = {{ | 59 | static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { |
| 55 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 | ||
| 56 | {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 | ||
| 57 | }}; | ||
| 58 | |||
| 59 | static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { | ||
| 60 | const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); | 60 | const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); |
| 61 | if (type == SurfaceType::Color) { | 61 | if (type == SurfaceType::ColorTexture) { |
| 62 | ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size()); | 62 | ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); |
| 63 | return fb_format_tuples[static_cast<unsigned int>(pixel_format)]; | 63 | // For now only UNORM components are supported |
| 64 | ASSERT(component_type == ComponentType::UNorm); | ||
| 65 | return tex_format_tuples[static_cast<unsigned int>(pixel_format)]; | ||
| 64 | } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { | 66 | } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { |
| 65 | // TODO(Subv): Implement depth formats | 67 | // TODO(Subv): Implement depth formats |
| 66 | ASSERT_MSG(false, "Unimplemented"); | 68 | ASSERT_MSG(false, "Unimplemented"); |
| 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)]; | ||
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | UNREACHABLE(); | 71 | UNREACHABLE(); |
| @@ -85,56 +84,42 @@ static u16 GetResolutionScaleFactor() { | |||
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | template <bool morton_to_gl, PixelFormat format> | 86 | template <bool morton_to_gl, PixelFormat format> |
| 88 | static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) { | 87 | void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start, |
| 88 | VAddr end) { | ||
| 89 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; | 89 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; |
| 90 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); | 90 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); |
| 91 | for (u32 y = 0; y < 8; ++y) { | ||
| 92 | for (u32 x = 0; x < 8; ++x) { | ||
| 93 | u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel; | ||
| 94 | u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel; | ||
| 95 | if (morton_to_gl) { | ||
| 96 | std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel); | ||
| 97 | } else { | ||
| 98 | std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | template <bool morton_to_gl, PixelFormat format> | ||
| 105 | void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) { | ||
| 106 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; | ||
| 107 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); | ||
| 108 | |||
| 109 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the | ||
| 110 | // configuration for this and perform more generic un/swizzle | ||
| 111 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | ||
| 112 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, | ||
| 113 | Memory::GetPointer(base), gl_buffer, morton_to_gl); | ||
| 114 | } | ||
| 115 | 91 | ||
| 116 | template <> | 92 | if (morton_to_gl) { |
| 117 | void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base, | 93 | auto data = Tegra::Texture::UnswizzleTexture( |
| 118 | VAddr start, VAddr end) { | 94 | base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, |
| 119 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8; | 95 | block_height); |
| 120 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1); | 96 | std::memcpy(gl_buffer, data.data(), data.size()); |
| 121 | 97 | } else { | |
| 122 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the | 98 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check |
| 123 | // configuration for this and perform more generic un/swizzle | 99 | // the configuration for this and perform more generic un/swizzle |
| 124 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | 100 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); |
| 125 | auto data = | 101 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, |
| 126 | Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height); | 102 | Memory::GetPointer(base), gl_buffer, morton_to_gl); |
| 127 | std::memcpy(gl_buffer, data.data(), data.size()); | 103 | } |
| 128 | } | 104 | } |
| 129 | 105 | ||
| 130 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { | 106 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), |
| 131 | MortonCopy<true, PixelFormat::RGBA8>, | 107 | SurfaceParams::MaxPixelFormat> |
| 132 | MortonCopy<true, PixelFormat::DXT1>, | 108 | morton_to_gl_fns = { |
| 109 | MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, | ||
| 110 | MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, | ||
| 111 | MortonCopy<true, PixelFormat::DXT45>, | ||
| 133 | }; | 112 | }; |
| 134 | 113 | ||
| 135 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { | 114 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), |
| 136 | MortonCopy<false, PixelFormat::RGBA8>, | 115 | SurfaceParams::MaxPixelFormat> |
| 137 | MortonCopy<false, PixelFormat::DXT1>, | 116 | gl_to_morton_fns = { |
| 117 | MortonCopy<false, PixelFormat::ABGR8>, | ||
| 118 | MortonCopy<false, PixelFormat::B5G6R5>, | ||
| 119 | // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported | ||
| 120 | nullptr, | ||
| 121 | nullptr, | ||
| 122 | nullptr, | ||
| 138 | }; | 123 | }; |
| 139 | 124 | ||
| 140 | // Allocate an uninitialized texture of appropriate size and format for the surface | 125 | // Allocate an uninitialized texture of appropriate size and format for the surface |
| @@ -183,7 +168,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec | |||
| 183 | 168 | ||
| 184 | u32 buffers = 0; | 169 | u32 buffers = 0; |
| 185 | 170 | ||
| 186 | if (type == SurfaceType::Color || type == SurfaceType::Texture) { | 171 | if (type == SurfaceType::ColorTexture) { |
| 187 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, | 172 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, |
| 188 | 0); | 173 | 0); |
| 189 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | 174 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, |
| @@ -311,15 +296,18 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su | |||
| 311 | 296 | ||
| 312 | bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { | 297 | bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { |
| 313 | return std::tie(other_surface.addr, other_surface.width, other_surface.height, | 298 | return std::tie(other_surface.addr, other_surface.width, other_surface.height, |
| 314 | other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == | 299 | other_surface.stride, other_surface.block_height, other_surface.pixel_format, |
| 315 | std::tie(addr, width, height, stride, pixel_format, is_tiled) && | 300 | other_surface.component_type, |
| 301 | other_surface.is_tiled) == std::tie(addr, width, height, stride, block_height, | ||
| 302 | pixel_format, component_type, is_tiled) && | ||
| 316 | pixel_format != PixelFormat::Invalid; | 303 | pixel_format != PixelFormat::Invalid; |
| 317 | } | 304 | } |
| 318 | 305 | ||
| 319 | bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { | 306 | bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { |
| 320 | return sub_surface.addr >= addr && sub_surface.end <= end && | 307 | return sub_surface.addr >= addr && sub_surface.end <= end && |
| 321 | sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && | 308 | sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && |
| 322 | sub_surface.is_tiled == is_tiled && | 309 | sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height && |
| 310 | sub_surface.component_type == component_type && | ||
| 323 | (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && | 311 | (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && |
| 324 | (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && | 312 | (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && |
| 325 | GetSubRect(sub_surface).left + sub_surface.width <= stride; | 313 | GetSubRect(sub_surface).left + sub_surface.width <= stride; |
| @@ -328,7 +316,8 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { | |||
| 328 | bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { | 316 | bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { |
| 329 | return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && | 317 | return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && |
| 330 | addr <= expanded_surface.end && expanded_surface.addr <= end && | 318 | addr <= expanded_surface.end && expanded_surface.addr <= end && |
| 331 | is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride && | 319 | is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height && |
| 320 | component_type == expanded_surface.component_type && stride == expanded_surface.stride && | ||
| 332 | (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % | 321 | (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % |
| 333 | BytesInPixels(stride * (is_tiled ? 8 : 1)) == | 322 | BytesInPixels(stride * (is_tiled ? 8 : 1)) == |
| 334 | 0; | 323 | 0; |
| @@ -339,6 +328,10 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const { | |||
| 339 | end < texcopy_params.end) { | 328 | end < texcopy_params.end) { |
| 340 | return false; | 329 | return false; |
| 341 | } | 330 | } |
| 331 | if (texcopy_params.block_height != block_height || | ||
| 332 | texcopy_params.component_type != component_type) | ||
| 333 | return false; | ||
| 334 | |||
| 342 | if (texcopy_params.width != texcopy_params.stride) { | 335 | if (texcopy_params.width != texcopy_params.stride) { |
| 343 | const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); | 336 | const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); |
| 344 | return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && | 337 | return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && |
| @@ -481,18 +474,13 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) { | |||
| 481 | const u64 start_offset = load_start - addr; | 474 | const u64 start_offset = load_start - addr; |
| 482 | 475 | ||
| 483 | if (!is_tiled) { | 476 | if (!is_tiled) { |
| 484 | ASSERT(type == SurfaceType::Color); | ||
| 485 | const u32 bytes_per_pixel{GetFormatBpp() >> 3}; | 477 | const u32 bytes_per_pixel{GetFormatBpp() >> 3}; |
| 486 | 478 | ||
| 487 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check | 479 | std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset, |
| 488 | // the configuration for this and perform more generic un/swizzle | 480 | bytes_per_pixel * width * height); |
| 489 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | ||
| 490 | VideoCore::MortonCopyPixels128(width, height, bytes_per_pixel, 4, | ||
| 491 | texture_src_data + start_offset, &gl_buffer[start_offset], | ||
| 492 | true); | ||
| 493 | } else { | 481 | } else { |
| 494 | morton_to_gl_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, | 482 | morton_to_gl_fns[static_cast<size_t>(pixel_format)]( |
| 495 | load_start, load_end); | 483 | stride, block_height, height, &gl_buffer[0], addr, load_start, load_end); |
| 496 | } | 484 | } |
| 497 | } | 485 | } |
| 498 | 486 | ||
| @@ -533,11 +521,10 @@ void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) { | |||
| 533 | if (backup_bytes) | 521 | if (backup_bytes) |
| 534 | std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); | 522 | std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); |
| 535 | } else if (!is_tiled) { | 523 | } else if (!is_tiled) { |
| 536 | ASSERT(type == SurfaceType::Color); | ||
| 537 | std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); | 524 | std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); |
| 538 | } else { | 525 | } else { |
| 539 | gl_to_morton_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, | 526 | gl_to_morton_fns[static_cast<size_t>(pixel_format)]( |
| 540 | flush_start, flush_end); | 527 | stride, block_height, height, &gl_buffer[0], addr, flush_start, flush_end); |
| 541 | } | 528 | } |
| 542 | } | 529 | } |
| 543 | 530 | ||
| @@ -556,7 +543,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint | |||
| 556 | GLint y0 = static_cast<GLint>(rect.bottom); | 543 | GLint y0 = static_cast<GLint>(rect.bottom); |
| 557 | size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format); | 544 | size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format); |
| 558 | 545 | ||
| 559 | const FormatTuple& tuple = GetFormatTuple(pixel_format); | 546 | const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type); |
| 560 | GLuint target_tex = texture.handle; | 547 | GLuint target_tex = texture.handle; |
| 561 | 548 | ||
| 562 | // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in | 549 | // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in |
| @@ -629,7 +616,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui | |||
| 629 | OpenGLState prev_state = state; | 616 | OpenGLState prev_state = state; |
| 630 | SCOPE_EXIT({ prev_state.Apply(); }); | 617 | SCOPE_EXIT({ prev_state.Apply(); }); |
| 631 | 618 | ||
| 632 | const FormatTuple& tuple = GetFormatTuple(pixel_format); | 619 | const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type); |
| 633 | 620 | ||
| 634 | // Ensure no bad interactions with GL_PACK_ALIGNMENT | 621 | // Ensure no bad interactions with GL_PACK_ALIGNMENT |
| 635 | ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); | 622 | ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); |
| @@ -662,7 +649,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui | |||
| 662 | state.draw.read_framebuffer = read_fb_handle; | 649 | state.draw.read_framebuffer = read_fb_handle; |
| 663 | state.Apply(); | 650 | state.Apply(); |
| 664 | 651 | ||
| 665 | if (type == SurfaceType::Color || type == SurfaceType::Texture) { | 652 | if (type == SurfaceType::ColorTexture) { |
| 666 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 653 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |
| 667 | texture.handle, 0); | 654 | texture.handle, 0); |
| 668 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | 655 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, |
| @@ -1041,9 +1028,25 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu | |||
| 1041 | params.height = config.tic.Height(); | 1028 | params.height = config.tic.Height(); |
| 1042 | params.is_tiled = config.tic.IsTiled(); | 1029 | params.is_tiled = config.tic.IsTiled(); |
| 1043 | params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); | 1030 | params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); |
| 1031 | |||
| 1032 | // TODO(Subv): Different types per component are not supported. | ||
| 1033 | ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() && | ||
| 1034 | config.tic.r_type.Value() == config.tic.b_type.Value() && | ||
| 1035 | config.tic.r_type.Value() == config.tic.a_type.Value()); | ||
| 1036 | |||
| 1037 | params.component_type = SurfaceParams::ComponentTypeFromTexture(config.tic.r_type.Value()); | ||
| 1038 | |||
| 1039 | if (config.tic.IsTiled()) { | ||
| 1040 | params.block_height = config.tic.BlockHeight(); | ||
| 1041 | } else { | ||
| 1042 | // Use the texture-provided stride value if the texture isn't tiled. | ||
| 1043 | params.stride = params.PixelsInBytes(config.tic.Pitch()); | ||
| 1044 | } | ||
| 1045 | |||
| 1044 | params.UpdateParams(); | 1046 | params.UpdateParams(); |
| 1045 | 1047 | ||
| 1046 | if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) { | 1048 | if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 || |
| 1049 | params.stride != params.width) { | ||
| 1047 | Surface src_surface; | 1050 | Surface src_surface; |
| 1048 | MathUtil::Rectangle<u32> rect; | 1051 | MathUtil::Rectangle<u32> rect; |
| 1049 | std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); | 1052 | std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); |
| @@ -1094,10 +1097,13 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
| 1094 | color_params.res_scale = resolution_scale_factor; | 1097 | color_params.res_scale = resolution_scale_factor; |
| 1095 | color_params.width = config.width; | 1098 | color_params.width = config.width; |
| 1096 | color_params.height = config.height; | 1099 | color_params.height = config.height; |
| 1100 | // TODO(Subv): Can framebuffers use a different block height? | ||
| 1101 | color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; | ||
| 1097 | SurfaceParams depth_params = color_params; | 1102 | SurfaceParams depth_params = color_params; |
| 1098 | 1103 | ||
| 1099 | color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); | 1104 | color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); |
| 1100 | color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); | 1105 | color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); |
| 1106 | color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); | ||
| 1101 | color_params.UpdateParams(); | 1107 | color_params.UpdateParams(); |
| 1102 | 1108 | ||
| 1103 | ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); | 1109 | ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); |
| @@ -1293,7 +1299,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface | |||
| 1293 | const SurfaceInterval invalid_interval(addr, addr + size); | 1299 | const SurfaceInterval invalid_interval(addr, addr + size); |
| 1294 | 1300 | ||
| 1295 | if (region_owner != nullptr) { | 1301 | if (region_owner != nullptr) { |
| 1296 | ASSERT(region_owner->type != SurfaceType::Texture); | ||
| 1297 | ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end); | 1302 | ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end); |
| 1298 | // Surfaces can't have a gap | 1303 | // Surfaces can't have a gap |
| 1299 | ASSERT(region_owner->width == region_owner->stride); | 1304 | ASSERT(region_owner->width == region_owner->stride); |
| @@ -1355,7 +1360,8 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) { | |||
| 1355 | 1360 | ||
| 1356 | surface->gl_buffer_size = 0; | 1361 | surface->gl_buffer_size = 0; |
| 1357 | surface->invalid_regions.insert(surface->GetInterval()); | 1362 | surface->invalid_regions.insert(surface->GetInterval()); |
| 1358 | AllocateSurfaceTexture(surface->texture.handle, GetFormatTuple(surface->pixel_format), | 1363 | AllocateSurfaceTexture(surface->texture.handle, |
| 1364 | GetFormatTuple(surface->pixel_format, surface->component_type), | ||
| 1359 | surface->GetScaledWidth(), surface->GetScaledHeight()); | 1365 | surface->GetScaledWidth(), surface->GetScaledHeight()); |
| 1360 | 1366 | ||
| 1361 | return surface; | 1367 | return surface; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 3293905d6..6861efe16 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -52,27 +52,45 @@ enum class ScaleMatch { | |||
| 52 | 52 | ||
| 53 | struct SurfaceParams { | 53 | struct SurfaceParams { |
| 54 | enum class PixelFormat { | 54 | enum class PixelFormat { |
| 55 | RGBA8 = 0, | 55 | ABGR8 = 0, |
| 56 | DXT1 = 1, | 56 | B5G6R5 = 1, |
| 57 | DXT1 = 2, | ||
| 58 | DXT23 = 3, | ||
| 59 | DXT45 = 4, | ||
| 60 | |||
| 61 | Max, | ||
| 57 | Invalid = 255, | 62 | Invalid = 255, |
| 58 | }; | 63 | }; |
| 59 | 64 | ||
| 65 | static constexpr size_t MaxPixelFormat = static_cast<size_t>(PixelFormat::Max); | ||
| 66 | |||
| 67 | enum class ComponentType { | ||
| 68 | Invalid = 0, | ||
| 69 | SNorm = 1, | ||
| 70 | UNorm = 2, | ||
| 71 | SInt = 3, | ||
| 72 | UInt = 4, | ||
| 73 | Float = 5, | ||
| 74 | }; | ||
| 75 | |||
| 60 | enum class SurfaceType { | 76 | enum class SurfaceType { |
| 61 | Color = 0, | 77 | ColorTexture = 0, |
| 62 | Texture = 1, | 78 | Depth = 1, |
| 63 | Depth = 2, | 79 | DepthStencil = 2, |
| 64 | DepthStencil = 3, | 80 | Fill = 3, |
| 65 | Fill = 4, | 81 | Invalid = 4, |
| 66 | Invalid = 5 | ||
| 67 | }; | 82 | }; |
| 68 | 83 | ||
| 69 | static constexpr unsigned int GetFormatBpp(PixelFormat format) { | 84 | static constexpr unsigned int GetFormatBpp(PixelFormat format) { |
| 70 | if (format == PixelFormat::Invalid) | 85 | if (format == PixelFormat::Invalid) |
| 71 | return 0; | 86 | return 0; |
| 72 | 87 | ||
| 73 | constexpr std::array<unsigned int, 2> bpp_table = { | 88 | constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = { |
| 74 | 32, // RGBA8 | 89 | 32, // ABGR8 |
| 75 | 64, // DXT1 | 90 | 16, // B5G6R5 |
| 91 | 64, // DXT1 | ||
| 92 | 128, // DXT23 | ||
| 93 | 128, // DXT45 | ||
| 76 | }; | 94 | }; |
| 77 | 95 | ||
| 78 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); | 96 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); |
| @@ -85,7 +103,7 @@ struct SurfaceParams { | |||
| 85 | static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { | 103 | static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { |
| 86 | switch (format) { | 104 | switch (format) { |
| 87 | case Tegra::RenderTargetFormat::RGBA8_UNORM: | 105 | case Tegra::RenderTargetFormat::RGBA8_UNORM: |
| 88 | return PixelFormat::RGBA8; | 106 | return PixelFormat::ABGR8; |
| 89 | default: | 107 | default: |
| 90 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 108 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); |
| 91 | UNREACHABLE(); | 109 | UNREACHABLE(); |
| @@ -95,7 +113,7 @@ struct SurfaceParams { | |||
| 95 | static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { | 113 | static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { |
| 96 | switch (format) { | 114 | switch (format) { |
| 97 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: | 115 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: |
| 98 | return PixelFormat::RGBA8; | 116 | return PixelFormat::ABGR8; |
| 99 | default: | 117 | default: |
| 100 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 118 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); |
| 101 | UNREACHABLE(); | 119 | UNREACHABLE(); |
| @@ -106,9 +124,67 @@ struct SurfaceParams { | |||
| 106 | // TODO(Subv): Properly implement this | 124 | // TODO(Subv): Properly implement this |
| 107 | switch (format) { | 125 | switch (format) { |
| 108 | case Tegra::Texture::TextureFormat::A8R8G8B8: | 126 | case Tegra::Texture::TextureFormat::A8R8G8B8: |
| 109 | return PixelFormat::RGBA8; | 127 | return PixelFormat::ABGR8; |
| 128 | case Tegra::Texture::TextureFormat::B5G6R5: | ||
| 129 | return PixelFormat::B5G6R5; | ||
| 110 | case Tegra::Texture::TextureFormat::DXT1: | 130 | case Tegra::Texture::TextureFormat::DXT1: |
| 111 | return PixelFormat::DXT1; | 131 | return PixelFormat::DXT1; |
| 132 | case Tegra::Texture::TextureFormat::DXT23: | ||
| 133 | return PixelFormat::DXT23; | ||
| 134 | case Tegra::Texture::TextureFormat::DXT45: | ||
| 135 | return PixelFormat::DXT45; | ||
| 136 | default: | ||
| 137 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | ||
| 138 | UNREACHABLE(); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) { | ||
| 143 | // TODO(Subv): Properly implement this | ||
| 144 | switch (format) { | ||
| 145 | case PixelFormat::ABGR8: | ||
| 146 | return Tegra::Texture::TextureFormat::A8R8G8B8; | ||
| 147 | case PixelFormat::B5G6R5: | ||
| 148 | return Tegra::Texture::TextureFormat::B5G6R5; | ||
| 149 | case PixelFormat::DXT1: | ||
| 150 | return Tegra::Texture::TextureFormat::DXT1; | ||
| 151 | case PixelFormat::DXT23: | ||
| 152 | return Tegra::Texture::TextureFormat::DXT23; | ||
| 153 | case PixelFormat::DXT45: | ||
| 154 | return Tegra::Texture::TextureFormat::DXT45; | ||
| 155 | default: | ||
| 156 | UNREACHABLE(); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { | ||
| 161 | // TODO(Subv): Implement more component types | ||
| 162 | switch (type) { | ||
| 163 | case Tegra::Texture::ComponentType::UNORM: | ||
| 164 | return ComponentType::UNorm; | ||
| 165 | default: | ||
| 166 | NGLOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type)); | ||
| 167 | UNREACHABLE(); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | static ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) { | ||
| 172 | // TODO(Subv): Implement more render targets | ||
| 173 | switch (format) { | ||
| 174 | case Tegra::RenderTargetFormat::RGBA8_UNORM: | ||
| 175 | case Tegra::RenderTargetFormat::RGB10_A2_UNORM: | ||
| 176 | return ComponentType::UNorm; | ||
| 177 | default: | ||
| 178 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | ||
| 179 | UNREACHABLE(); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | static ComponentType ComponentTypeFromGPUPixelFormat( | ||
| 184 | Tegra::FramebufferConfig::PixelFormat format) { | ||
| 185 | switch (format) { | ||
| 186 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: | ||
| 187 | return ComponentType::UNorm; | ||
| 112 | default: | 188 | default: |
| 113 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 189 | NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); |
| 114 | UNREACHABLE(); | 190 | UNREACHABLE(); |
| @@ -119,8 +195,7 @@ struct SurfaceParams { | |||
| 119 | SurfaceType a_type = GetFormatType(pixel_format_a); | 195 | SurfaceType a_type = GetFormatType(pixel_format_a); |
| 120 | SurfaceType b_type = GetFormatType(pixel_format_b); | 196 | SurfaceType b_type = GetFormatType(pixel_format_b); |
| 121 | 197 | ||
| 122 | if ((a_type == SurfaceType::Color || a_type == SurfaceType::Texture) && | 198 | if (a_type == SurfaceType::ColorTexture && b_type == SurfaceType::ColorTexture) { |
| 123 | (b_type == SurfaceType::Color || b_type == SurfaceType::Texture)) { | ||
| 124 | return true; | 199 | return true; |
| 125 | } | 200 | } |
| 126 | 201 | ||
| @@ -136,12 +211,8 @@ struct SurfaceParams { | |||
| 136 | } | 211 | } |
| 137 | 212 | ||
| 138 | static SurfaceType GetFormatType(PixelFormat pixel_format) { | 213 | static SurfaceType GetFormatType(PixelFormat pixel_format) { |
| 139 | if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::RGBA8)) { | 214 | if (static_cast<size_t>(pixel_format) < MaxPixelFormat) { |
| 140 | return SurfaceType::Color; | 215 | return SurfaceType::ColorTexture; |
| 141 | } | ||
| 142 | |||
| 143 | if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::DXT1)) { | ||
| 144 | return SurfaceType::Texture; | ||
| 145 | } | 216 | } |
| 146 | 217 | ||
| 147 | // TODO(Subv): Implement the other formats | 218 | // TODO(Subv): Implement the other formats |
| @@ -213,11 +284,13 @@ struct SurfaceParams { | |||
| 213 | u32 width = 0; | 284 | u32 width = 0; |
| 214 | u32 height = 0; | 285 | u32 height = 0; |
| 215 | u32 stride = 0; | 286 | u32 stride = 0; |
| 287 | u32 block_height = 0; | ||
| 216 | u16 res_scale = 1; | 288 | u16 res_scale = 1; |
| 217 | 289 | ||
| 218 | bool is_tiled = false; | 290 | bool is_tiled = false; |
| 219 | PixelFormat pixel_format = PixelFormat::Invalid; | 291 | PixelFormat pixel_format = PixelFormat::Invalid; |
| 220 | SurfaceType type = SurfaceType::Invalid; | 292 | SurfaceType type = SurfaceType::Invalid; |
| 293 | ComponentType component_type = ComponentType::Invalid; | ||
| 221 | }; | 294 | }; |
| 222 | 295 | ||
| 223 | struct CachedSurface : SurfaceParams { | 296 | struct CachedSurface : SurfaceParams { |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 8b7f17601..254f6e2c3 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -29,9 +29,15 @@ out gl_PerVertex { | |||
| 29 | 29 | ||
| 30 | out vec4 position; | 30 | out vec4 position; |
| 31 | 31 | ||
| 32 | layout (std140) uniform vs_config { | ||
| 33 | vec4 viewport_flip; | ||
| 34 | }; | ||
| 35 | |||
| 32 | void main() { | 36 | void main() { |
| 33 | exec_shader(); | 37 | exec_shader(); |
| 34 | 38 | ||
| 39 | // Viewport can be flipped, which is unsupported by glViewport | ||
| 40 | position.xy *= viewport_flip.xy; | ||
| 35 | gl_Position = position; | 41 | gl_Position = position; |
| 36 | } | 42 | } |
| 37 | )"; | 43 | )"; |
| @@ -52,6 +58,10 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSCo | |||
| 52 | in vec4 position; | 58 | in vec4 position; |
| 53 | out vec4 color; | 59 | out vec4 color; |
| 54 | 60 | ||
| 61 | layout (std140) uniform fs_config { | ||
| 62 | vec4 viewport_flip; | ||
| 63 | }; | ||
| 64 | |||
| 55 | uniform sampler2D tex[32]; | 65 | uniform sampler2D tex[32]; |
| 56 | 66 | ||
| 57 | void main() { | 67 | void main() { |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 85b838faa..17b3925a0 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -53,6 +53,12 @@ void SetShaderSamplerBindings(GLuint shader) { | |||
| 53 | 53 | ||
| 54 | } // namespace Impl | 54 | } // namespace Impl |
| 55 | 55 | ||
| 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {} | 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { |
| 57 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; | ||
| 58 | |||
| 59 | // TODO(bunnei): Support more than one viewport | ||
| 60 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0 : 1.0; | ||
| 61 | viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0 : 1.0; | ||
| 62 | } | ||
| 57 | 63 | ||
| 58 | } // namespace GLShader | 64 | } // namespace GLShader |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index be63320e0..e963b4b7e 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -30,10 +30,9 @@ void SetShaderSamplerBindings(GLuint shader); | |||
| 30 | // Not following that rule will cause problems on some AMD drivers. | 30 | // Not following that rule will cause problems on some AMD drivers. |
| 31 | struct MaxwellUniformData { | 31 | struct MaxwellUniformData { |
| 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); |
| 33 | // TODO(Subv): Use this for something. | 33 | alignas(16) GLvec4 viewport_flip; |
| 34 | }; | 34 | }; |
| 35 | // static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is | 35 | static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect"); |
| 36 | // incorrect"); | ||
| 37 | static_assert(sizeof(MaxwellUniformData) < 16384, | 36 | static_assert(sizeof(MaxwellUniformData) < 16384, |
| 38 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | 37 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); |
| 39 | 38 | ||
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 2e87281eb..4df687786 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -48,31 +48,39 @@ u32 BytesPerPixel(TextureFormat format) { | |||
| 48 | case TextureFormat::DXT1: | 48 | case TextureFormat::DXT1: |
| 49 | // In this case a 'pixel' actually refers to a 4x4 tile. | 49 | // In this case a 'pixel' actually refers to a 4x4 tile. |
| 50 | return 8; | 50 | return 8; |
| 51 | case TextureFormat::DXT23: | ||
| 52 | case TextureFormat::DXT45: | ||
| 53 | // In this case a 'pixel' actually refers to a 4x4 tile. | ||
| 54 | return 16; | ||
| 51 | case TextureFormat::A8R8G8B8: | 55 | case TextureFormat::A8R8G8B8: |
| 52 | return 4; | 56 | return 4; |
| 57 | case TextureFormat::B5G6R5: | ||
| 58 | return 2; | ||
| 53 | default: | 59 | default: |
| 54 | UNIMPLEMENTED_MSG("Format not implemented"); | 60 | UNIMPLEMENTED_MSG("Format not implemented"); |
| 55 | break; | 61 | break; |
| 56 | } | 62 | } |
| 57 | } | 63 | } |
| 58 | 64 | ||
| 59 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { | 65 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, |
| 66 | u32 block_height) { | ||
| 60 | u8* data = Memory::GetPointer(address); | 67 | u8* data = Memory::GetPointer(address); |
| 61 | u32 bytes_per_pixel = BytesPerPixel(format); | 68 | u32 bytes_per_pixel = BytesPerPixel(format); |
| 62 | 69 | ||
| 63 | static constexpr u32 DefaultBlockHeight = 16; | ||
| 64 | |||
| 65 | std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); | 70 | std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); |
| 66 | 71 | ||
| 67 | switch (format) { | 72 | switch (format) { |
| 68 | case TextureFormat::DXT1: | 73 | case TextureFormat::DXT1: |
| 69 | // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. | 74 | case TextureFormat::DXT23: |
| 75 | case TextureFormat::DXT45: | ||
| 76 | // In the DXT formats, each 4x4 tile is swizzled instead of just individual pixel values. | ||
| 70 | CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, | 77 | CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, |
| 71 | unswizzled_data.data(), true, DefaultBlockHeight); | 78 | unswizzled_data.data(), true, block_height); |
| 72 | break; | 79 | break; |
| 73 | case TextureFormat::A8R8G8B8: | 80 | case TextureFormat::A8R8G8B8: |
| 81 | case TextureFormat::B5G6R5: | ||
| 74 | CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, | 82 | CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, |
| 75 | unswizzled_data.data(), true, DefaultBlockHeight); | 83 | unswizzled_data.data(), true, block_height); |
| 76 | break; | 84 | break; |
| 77 | default: | 85 | default: |
| 78 | UNIMPLEMENTED_MSG("Format not implemented"); | 86 | UNIMPLEMENTED_MSG("Format not implemented"); |
| @@ -89,7 +97,10 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat | |||
| 89 | // TODO(Subv): Implement. | 97 | // TODO(Subv): Implement. |
| 90 | switch (format) { | 98 | switch (format) { |
| 91 | case TextureFormat::DXT1: | 99 | case TextureFormat::DXT1: |
| 100 | case TextureFormat::DXT23: | ||
| 101 | case TextureFormat::DXT45: | ||
| 92 | case TextureFormat::A8R8G8B8: | 102 | case TextureFormat::A8R8G8B8: |
| 103 | case TextureFormat::B5G6R5: | ||
| 93 | // TODO(Subv): For the time being just forward the same data without any decoding. | 104 | // TODO(Subv): For the time being just forward the same data without any decoding. |
| 94 | rgba_data = texture_data; | 105 | rgba_data = texture_data; |
| 95 | break; | 106 | break; |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index 0c21694ff..a700911cf 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -14,7 +14,8 @@ namespace Texture { | |||
| 14 | /** | 14 | /** |
| 15 | * Unswizzles a swizzled texture without changing its format. | 15 | * Unswizzles a swizzled texture without changing its format. |
| 16 | */ | 16 | */ |
| 17 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); | 17 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, |
| 18 | u32 block_height = TICEntry::DefaultBlockHeight); | ||
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 20 | * Decodes an unswizzled texture into a A8R8G8B8 texture. | 21 | * Decodes an unswizzled texture into a A8R8G8B8 texture. |
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 9d443ea90..86e45aa88 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | ||
| 7 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -14,6 +15,7 @@ namespace Texture { | |||
| 14 | 15 | ||
| 15 | enum class TextureFormat : u32 { | 16 | enum class TextureFormat : u32 { |
| 16 | A8R8G8B8 = 0x8, | 17 | A8R8G8B8 = 0x8, |
| 18 | B5G6R5 = 0x15, | ||
| 17 | DXT1 = 0x24, | 19 | DXT1 = 0x24, |
| 18 | DXT23 = 0x25, | 20 | DXT23 = 0x25, |
| 19 | DXT45 = 0x26, | 21 | DXT45 = 0x26, |
| @@ -57,6 +59,8 @@ union TextureHandle { | |||
| 57 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); | 59 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); |
| 58 | 60 | ||
| 59 | struct TICEntry { | 61 | struct TICEntry { |
| 62 | static constexpr u32 DefaultBlockHeight = 16; | ||
| 63 | |||
| 60 | union { | 64 | union { |
| 61 | u32 raw; | 65 | u32 raw; |
| 62 | BitField<0, 7, TextureFormat> format; | 66 | BitField<0, 7, TextureFormat> format; |
| @@ -70,7 +74,12 @@ struct TICEntry { | |||
| 70 | BitField<0, 16, u32> address_high; | 74 | BitField<0, 16, u32> address_high; |
| 71 | BitField<21, 3, TICHeaderVersion> header_version; | 75 | BitField<21, 3, TICHeaderVersion> header_version; |
| 72 | }; | 76 | }; |
| 73 | INSERT_PADDING_BYTES(4); | 77 | union { |
| 78 | BitField<3, 3, u32> block_height; | ||
| 79 | |||
| 80 | // High 16 bits of the pitch value | ||
| 81 | BitField<0, 16, u32> pitch_high; | ||
| 82 | }; | ||
| 74 | union { | 83 | union { |
| 75 | BitField<0, 16, u32> width_minus_1; | 84 | BitField<0, 16, u32> width_minus_1; |
| 76 | BitField<23, 4, TextureType> texture_type; | 85 | BitField<23, 4, TextureType> texture_type; |
| @@ -82,6 +91,13 @@ struct TICEntry { | |||
| 82 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); | 91 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); |
| 83 | } | 92 | } |
| 84 | 93 | ||
| 94 | u32 Pitch() const { | ||
| 95 | ASSERT(header_version == TICHeaderVersion::Pitch || | ||
| 96 | header_version == TICHeaderVersion::PitchColorKey); | ||
| 97 | // The pitch value is 21 bits, and is 32B aligned. | ||
| 98 | return pitch_high << 5; | ||
| 99 | } | ||
| 100 | |||
| 85 | u32 Width() const { | 101 | u32 Width() const { |
| 86 | return width_minus_1 + 1; | 102 | return width_minus_1 + 1; |
| 87 | } | 103 | } |
| @@ -90,6 +106,13 @@ struct TICEntry { | |||
| 90 | return height_minus_1 + 1; | 106 | return height_minus_1 + 1; |
| 91 | } | 107 | } |
| 92 | 108 | ||
| 109 | u32 BlockHeight() const { | ||
| 110 | ASSERT(header_version == TICHeaderVersion::BlockLinear || | ||
| 111 | header_version == TICHeaderVersion::BlockLinearColorKey); | ||
| 112 | // The block height is stored in log2 format. | ||
| 113 | return 1 << block_height; | ||
| 114 | } | ||
| 115 | |||
| 93 | bool IsTiled() const { | 116 | bool IsTiled() const { |
| 94 | return header_version == TICHeaderVersion::BlockLinear || | 117 | return header_version == TICHeaderVersion::BlockLinear || |
| 95 | header_version == TICHeaderVersion::BlockLinearColorKey; | 118 | header_version == TICHeaderVersion::BlockLinearColorKey; |