diff --git a/src/SharpEmu.Libs/Gpu/Images/ImageRequestBuilders.ColorTarget.cs b/src/SharpEmu.Libs/Gpu/Images/ImageRequestBuilders.ColorTarget.cs index 1be295f..e23ac96 100644 --- a/src/SharpEmu.Libs/Gpu/Images/ImageRequestBuilders.ColorTarget.cs +++ b/src/SharpEmu.Libs/Gpu/Images/ImageRequestBuilders.ColorTarget.cs @@ -289,9 +289,16 @@ public static partial class ImageRequestBuilders var viewExtent = new Extent2D(Math.Max(width >> (int)words.MipLevel, 1), Math.Max(height >> (int)words.MipLevel, 1)); var viewDepth = Math.Max(depth >> (int)words.MipLevel, 1); - if (volume && (view.BaseLayer >= viewDepth || view.LayerCount > viewDepth - view.BaseLayer)) + if (volume && view.BaseLayer < viewDepth && view.LayerCount > viewDepth - view.BaseLayer) { - throw SubmissionScheduler.Fatal($"The 3D render-target view exceeds the mip depth: base={view.BaseLayer} count={view.LayerCount} depth={viewDepth} mip={words.MipLevel}."); + // Titles bind a whole volume with the last slice set to its depth, one past the end; + // the color block stops at the last slice of the mip. + view = view with { LayerCount = viewDepth - view.BaseLayer, ImageLayers = viewDepth }; + } + + if (volume && view.BaseLayer >= viewDepth) + { + throw SubmissionScheduler.Fatal($"The 3D render-target view starts past the mip depth: base={view.BaseLayer} count={view.LayerCount} depth={viewDepth} mip={words.MipLevel}."); } var description = ImageDescription.Create(); diff --git a/tests/SharpEmu.Libs.Tests/Gpu/Images/ImageRequestBuildersTests.cs b/tests/SharpEmu.Libs.Tests/Gpu/Images/ImageRequestBuildersTests.cs index 31b1a2e..0388856 100644 --- a/tests/SharpEmu.Libs.Tests/Gpu/Images/ImageRequestBuildersTests.cs +++ b/tests/SharpEmu.Libs.Tests/Gpu/Images/ImageRequestBuildersTests.cs @@ -145,6 +145,25 @@ public sealed class ImageRequestBuildersTests : IClassFixture(() => ImageRequestBuilders.ColorTarget( + RegisterWords.Color(Base, 32, 32, GuestTileMode.RenderTarget, sliceStart: 32, sliceMax: 32, dimension: 2, depth: 31), 0xF, 0, false)); + } + [Fact] public void ColorTarget_RejectsUnsupportedRegisterStates() {