diff --git a/README.md b/README.md
index e1397c65e..a0001ac04 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 yuzu emulator early access
 =============
 
-This is the source code for early-access 2916.
+This is the source code for early-access 2918.
 
 ## Legal Notice
 
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index fae6e5aff..e23eae36a 100755
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -246,7 +246,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
     entries.reserve(entries.size() + new_data.size());
 
     for (const auto& new_entry : new_data) {
-        entries.emplace_back(new_entry->GetName(), type, new_entry->GetSize());
+        entries.emplace_back(new_entry->GetName(), type,
+                             type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize());
     }
 }
 
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
index a97b143e4..e67e80fac 100755
--- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
@@ -67,6 +67,7 @@ std::string_view TextureType(IR::TextureInstInfo info) {
         case TextureType::ColorArray1D:
             return "SHADOWARRAY1D";
         case TextureType::Color2D:
+        case TextureType::Color2DRect:
             return "SHADOW2D";
         case TextureType::ColorArray2D:
             return "SHADOWARRAY2D";
@@ -86,6 +87,7 @@ std::string_view TextureType(IR::TextureInstInfo info) {
         case TextureType::ColorArray1D:
             return "ARRAY1D";
         case TextureType::Color2D:
+        case TextureType::Color2DRect:
             return "2D";
         case TextureType::ColorArray2D:
             return "ARRAY2D";
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 6af7e3fe6..cecdbb9d6 100755
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -466,6 +466,7 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value&
     case TextureType::ColorArray1D:
     case TextureType::Color2D:
     case TextureType::ColorCube:
+    case TextureType::Color2DRect:
         return ctx.AddU32x4(
             "{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst,
             texture, lod, texture);
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
index 221b06328..c767a9dc3 100755
--- a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
@@ -86,6 +86,7 @@ std::string_view SamplerType(TextureType type, bool is_depth) {
     case TextureType::ColorArray1D:
         return "sampler1DArray";
     case TextureType::Color2D:
+    case TextureType::Color2DRect:
         return "sampler2D";
     case TextureType::ColorArray2D:
         return "sampler2DArray";
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index d8d86c91a..fb5799c42 100755
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -453,6 +453,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
     case TextureType::ColorArray1D:
     case TextureType::Color2D:
     case TextureType::ColorCube:
+    case TextureType::Color2DRect:
         return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod),
                                         zero, mips());
     case TextureType::ColorArray2D:
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 98dd9035a..aecc4c612 100755
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -41,6 +41,7 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
     case TextureType::ColorArray1D:
         return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format);
     case TextureType::Color2D:
+    case TextureType::Color2DRect:
         return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format);
     case TextureType::ColorArray2D:
         return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format);
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index d2b658bca..11086ed8c 100755
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -1832,6 +1832,11 @@ Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod) {
     return Inst(op, handle, lod);
 }
 
+Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
+                                     TextureInstInfo info) {
+    return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod);
+}
+
 Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) {
     const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryLod
                                          : Opcode::BindlessImageQueryLod};
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index c29bda558..25839a371 100755
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -315,6 +315,8 @@ public:
                                                  const F32& dref, const F32& lod,
                                                  const Value& offset, TextureInstInfo info);
     [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod);
+    [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod,
+                                            TextureInstInfo info);
 
     [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords,
                                       TextureInstInfo info);
diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp
index 0d5f2e4d8..9198fa5f2 100755
--- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp
+++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp
@@ -16,6 +16,7 @@ namespace {
     switch (type) {
     case TextureType::Color2D:
     case TextureType::ColorArray2D:
+    case TextureType::Color2DRect:
         return true;
     case TextureType::Color1D:
     case TextureType::ColorArray1D:
@@ -132,7 +133,8 @@ void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) {
     const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
     switch (info.type) {
     case TextureType::Color2D:
-    case TextureType::ColorArray2D: {
+    case TextureType::ColorArray2D:
+    case TextureType::Color2DRect: {
         const IR::Value new_inst{&*block.PrependNewInst(it, inst)};
         const IR::U32 width{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 0)})};
         const IR::U32 height{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 1)})};
@@ -163,6 +165,7 @@ void ScaleIntegerComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_s
     const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 1)})};
     switch (info.type) {
     case TextureType::Color2D:
+    case TextureType::Color2DRect:
         inst.SetArg(index, ir.CompositeConstruct(x, y));
         break;
     case TextureType::ColorArray2D: {
@@ -193,6 +196,7 @@ void ScaleIntegerOffsetComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1
     switch (info.type) {
     case TextureType::ColorArray2D:
     case TextureType::Color2D:
+    case TextureType::Color2DRect:
         inst.SetArg(index, ir.CompositeConstruct(x, y));
         break;
     case TextureType::Color1D:
@@ -216,6 +220,7 @@ void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) {
     const IR::U32 scaled_y{SubScale(ir, is_scaled, coord_y, IR::Attribute::PositionY)};
     switch (info.type) {
     case TextureType::Color2D:
+    case TextureType::Color2DRect:
         inst.SetArg(1, ir.CompositeConstruct(scaled_x, scaled_y));
         break;
     case TextureType::ColorArray2D: {
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index cfce9e3da..e8637072e 100755
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -436,6 +436,21 @@ private:
     TextureDescriptors& texture_descriptors;
     ImageDescriptors& image_descriptors;
 };
+
+void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
+    IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
+    const auto info{inst.Flags<IR::TextureInstInfo>()};
+    const IR::Value coord(inst.Arg(1));
+    const IR::Value handle(ir.Imm32(0));
+    const IR::U32 lod{ir.Imm32(0)};
+    const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, info);
+    inst.SetArg(
+        1, ir.CompositeConstruct(
+               ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)),
+                        ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 0)))),
+               ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)),
+                        ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
+}
 } // Anonymous namespace
 
 void TexturePass(Environment& env, IR::Program& program) {
@@ -473,6 +488,14 @@ void TexturePass(Environment& env, IR::Program& program) {
             flags.type.Assign(ReadTextureType(env, cbuf));
             inst->SetFlags(flags);
             break;
+        case IR::Opcode::ImageSampleImplicitLod:
+            if (flags.type == TextureType::Color2D) {
+                auto texture_type = ReadTextureType(env, cbuf);
+                if (texture_type == TextureType::Color2DRect) {
+                    PatchImageSampleImplicitLod(*texture_inst.block, *texture_inst.inst);
+                }
+            }
+            break;
         case IR::Opcode::ImageFetch:
             if (flags.type != TextureType::Color1D) {
                 break;
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index 3a10b1b35..cc596da4f 100755
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -24,8 +24,9 @@ enum class TextureType : u32 {
     ColorCube,
     ColorArrayCube,
     Buffer,
+    Color2DRect,
 };
-constexpr u32 NUM_TEXTURE_TYPES = 8;
+constexpr u32 NUM_TEXTURE_TYPES = 9;
 
 enum class ImageFormat : u32 {
     Typeless,
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 8c0fffc67..99cd11d1e 100755
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -93,6 +93,7 @@ GLenum ImageTarget(Shader::TextureType type, int num_samples = 1) {
     case Shader::TextureType::Color1D:
         return GL_TEXTURE_1D;
     case Shader::TextureType::Color2D:
+    case Shader::TextureType::Color2DRect:
         return is_multisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
     case Shader::TextureType::ColorCube:
         return GL_TEXTURE_CUBE_MAP;
@@ -502,6 +503,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
     set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle);
     set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle);
     set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle);
+    set_view(Shader::TextureType::Color2DRect, null_image_view_2d.handle);
 
     if (resolution.active) {
         for (size_t i = 0; i < rescale_draw_fbos.size(); ++i) {
@@ -1110,6 +1112,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
         flat_range.extent.layers = 1;
         [[fallthrough]];
     case ImageViewType::e2D:
+    case ImageViewType::Rect:
         if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) {
             // 2D and 2D array views on a 3D textures are used exclusively for render targets
             ASSERT(info.range.extent.levels == 1);
@@ -1135,9 +1138,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
         SetupView(Shader::TextureType::ColorCube);
         SetupView(Shader::TextureType::ColorArrayCube);
         break;
-    case ImageViewType::Rect:
-        UNIMPLEMENTED();
-        break;
     case ImageViewType::Buffer:
         ASSERT(false);
         break;
@@ -1150,6 +1150,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
         default_handle = Handle(Shader::TextureType::ColorArray1D);
         break;
     case ImageViewType::e2D:
+    case ImageViewType::Rect:
         default_handle = Handle(Shader::TextureType::Color2D);
         break;
     case ImageViewType::e2DArray:
@@ -1210,6 +1211,7 @@ GLuint ImageView::MakeView(Shader::TextureType view_type, GLenum view_format) {
     case Shader::TextureType::Color1D:
     case Shader::TextureType::Color2D:
     case Shader::TextureType::ColorCube:
+    case Shader::TextureType::Color2DRect:
         view_range = flat_range;
         break;
     case Shader::TextureType::ColorArray1D:
@@ -1250,7 +1252,6 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) {
     const GLint seamless = config.cubemap_interface_filtering ? GL_TRUE : GL_FALSE;
 
     UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1);
-    UNIMPLEMENTED_IF(config.float_coord_normalization != 0);
 
     sampler.Create();
     const GLuint handle = sampler.handle;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 3b1ad1932..305ad8aee 100755
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -230,6 +230,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
     case Shader::TextureType::Color1D:
         return VK_IMAGE_VIEW_TYPE_1D;
     case Shader::TextureType::Color2D:
+    case Shader::TextureType::Color2DRect:
         return VK_IMAGE_VIEW_TYPE_2D;
     case Shader::TextureType::ColorCube:
         return VK_IMAGE_VIEW_TYPE_CUBE;
@@ -254,6 +255,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
     case VideoCommon::ImageViewType::e1D:
         return VK_IMAGE_VIEW_TYPE_1D;
     case VideoCommon::ImageViewType::e2D:
+    case VideoCommon::ImageViewType::Rect:
         return VK_IMAGE_VIEW_TYPE_2D;
     case VideoCommon::ImageViewType::Cube:
         return VK_IMAGE_VIEW_TYPE_CUBE;
@@ -265,9 +267,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
         return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
     case VideoCommon::ImageViewType::CubeArray:
         return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
-    case VideoCommon::ImageViewType::Rect:
-        UNIMPLEMENTED_MSG("Rect image view");
-        return VK_IMAGE_VIEW_TYPE_2D;
     case VideoCommon::ImageViewType::Buffer:
         ASSERT_MSG(false, "Texture buffers can't be image views");
         return VK_IMAGE_VIEW_TYPE_1D;
@@ -1581,6 +1580,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
         break;
     case VideoCommon::ImageViewType::e2D:
     case VideoCommon::ImageViewType::e2DArray:
+    case VideoCommon::ImageViewType::Rect:
         create(TextureType::Color2D, 1);
         create(TextureType::ColorArray2D, std::nullopt);
         render_target = Handle(Shader::TextureType::ColorArray2D);
@@ -1594,9 +1594,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
         create(TextureType::ColorCube, 6);
         create(TextureType::ColorArrayCube, std::nullopt);
         break;
-    case VideoCommon::ImageViewType::Rect:
-        UNIMPLEMENTED();
-        break;
     case VideoCommon::ImageViewType::Buffer:
         ASSERT(false);
         break;
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index c4e923bbf..808d88eec 100755
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -39,7 +39,11 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) {
         return Shader::TextureType::Color1D;
     case Tegra::Texture::TextureType::Texture2D:
     case Tegra::Texture::TextureType::Texture2DNoMipmap:
-        return Shader::TextureType::Color2D;
+        if (entry.normalized_coords) {
+            return Shader::TextureType::Color2D;
+        } else {
+            return Shader::TextureType::Color2DRect;
+        }
     case Tegra::Texture::TextureType::Texture3D:
         return Shader::TextureType::Color3D;
     case Tegra::Texture::TextureType::TextureCubemap:
@@ -53,7 +57,8 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) {
     case Tegra::Texture::TextureType::TextureCubeArray:
         return Shader::TextureType::ColorArrayCube;
     default:
-        throw Shader::NotImplementedException("Unknown texture type");
+        UNIMPLEMENTED();
+        return Shader::TextureType::Color2D;
     }
 }