diff --git a/src/graphics/host_gpu/renderer/colorRenderTarget.cpp b/src/graphics/host_gpu/renderer/colorRenderTarget.cpp index ead17aadc..81f118118 100644 --- a/src/graphics/host_gpu/renderer/colorRenderTarget.cpp +++ b/src/graphics/host_gpu/renderer/colorRenderTarget.cpp @@ -115,8 +115,41 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer& EXIT("unsupported render-target sample configuration: samples=%u fragments=%u\n", rt.attrib.num_samples, rt.attrib.num_fragments); } + const uint32_t levels = rt.attrib2.num_mip_levels + 1u; + if (levels == 0 || levels > 16 || rt.view.current_mip_level >= levels) { + EXIT("unsupported render-target mip range: current=%u levels=%u\n", + rt.view.current_mip_level, levels); + } + static constexpr std::array image_types {Prospero::ImageType::kColor1D, + Prospero::ImageType::kColor2D, + Prospero::ImageType::kColor3D}; + if (rt.attrib3.dimension >= image_types.size()) { + EXIT("unsupported render-target dimension: %u\n", rt.attrib3.dimension); + } + const auto image_type = image_types[rt.attrib3.dimension]; + const bool is_1d = image_type == Prospero::ImageType::kColor1D; + const bool volume = image_type == Prospero::ImageType::kColor3D; + if (is_1d && rt.attrib2.height != 0) { + EXIT("1D render target has nonzero height: %u\n", rt.attrib2.height); + } + if (!volume && rt.attrib3.depth != 0) { + EXIT("non-3D render target has nonzero depth: %u\n", rt.attrib3.depth); + } + if (is_1d && samples != 1) { + EXIT("multisampled 1D render targets are unsupported\n"); + } + if (volume && samples != 1) { + EXIT("multisampled 3D render targets are unsupported\n"); + } + const uint32_t depth = volume ? rt.attrib3.depth + 1u : 1u; + // For volumes, CB_COLOR_VIEW bounds exported slices; ATTRIB3 defines storage depth. + // The host attachment contains only the selected slices that exist in this mip. + const uint32_t last_layer = volume + ? std::min(rt.view.last_array_slice_index, + std::max(depth >> rt.view.current_mip_level, 1u) - 1u) + : rt.view.last_array_slice_index; const auto view = ResolveTargetViewInfo( - rt.view.base_array_slice_index, rt.view.last_array_slice_index, render_target_slice_offset); + rt.view.base_array_slice_index, last_layer, render_target_slice_offset); switch (view.type) { case TargetViewType::Image2D: case TargetViewType::Image2DArray: break; @@ -125,12 +158,7 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer& rt.view.base_array_slice_index, rt.view.last_array_slice_index, render_target_slice_offset); } - r.base_array_layer = view.base_layer; - const uint32_t levels = rt.attrib2.num_mip_levels + 1u; - if (levels == 0 || levels > 16 || rt.view.current_mip_level >= levels) { - EXIT("unsupported render-target mip range: current=%u levels=%u\n", - rt.view.current_mip_level, levels); - } + r.base_array_layer = view.base_layer; if (graphics_debug_dump_enabled()) { static std::atomic_uint log_count = 0; const auto log_id = log_count.fetch_add(1, std::memory_order_relaxed); @@ -159,28 +187,6 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer& uint32_t pitch = 0; uint64_t size = 0; bool tile = false; - static constexpr std::array image_types {Prospero::ImageType::kColor1D, - Prospero::ImageType::kColor2D, - Prospero::ImageType::kColor3D}; - if (rt.attrib3.dimension >= image_types.size()) { - EXIT("unsupported render-target dimension: %u\n", rt.attrib3.dimension); - } - const auto image_type = image_types[rt.attrib3.dimension]; - const bool is_1d = image_type == Prospero::ImageType::kColor1D; - const bool volume = image_type == Prospero::ImageType::kColor3D; - if (is_1d && rt.attrib2.height != 0) { - EXIT("1D render target has nonzero height: %u\n", rt.attrib2.height); - } - if (!volume && rt.attrib3.depth != 0) { - EXIT("non-3D render target has nonzero depth: %u\n", rt.attrib3.depth); - } - if (is_1d && samples != 1) { - EXIT("multisampled 1D render targets are unsupported\n"); - } - if (volume && samples != 1) { - EXIT("multisampled 3D render targets are unsupported\n"); - } - const uint32_t depth = volume ? rt.attrib3.depth + 1u : 1u; const bool standard4 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard4KB; const bool standard64 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard64KB; const bool depth_tile = rt.attrib3.tile_mode == Prospero::TileMode::kDepth; @@ -320,12 +326,6 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer& const vk::Extent2D view_extent = {std::max(width >> rt.view.current_mip_level, 1u), std::max(height >> rt.view.current_mip_level, 1u)}; - const uint32_t view_depth = std::max(depth >> rt.view.current_mip_level, 1u); - if (volume && - (view.base_layer >= view_depth || view.layer_count > view_depth - view.base_layer)) { - EXIT("3D render-target view exceeds mip depth: base=%u count=%u depth=%u mip=%u\n", - view.base_layer, view.layer_count, view_depth, rt.view.current_mip_level); - } auto decision_log_id = g_render_color_log_count.fetch_add(1); if (decision_log_id < 128) { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 0be17dcc6..30f8a897e 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -7544,6 +7544,30 @@ public: "render-target upload/readback lost the final Z slice"); DestroyBuffer(&slice_probe); + for (const uint32_t base_slice : {0u, 7u}) { + RenderExecutorTestAccess::ResetBindings(executor); + registers.SetColorView(0, {.base_array_slice_index = base_slice, + .last_array_slice_index = 32}); + RenderColorInfo volume_color{}; + RenderExecutorTestAccess::ResolveRenderColorTarget( + executor, 3, scheduler.Current(), volume_color, 0); + const auto volume_rendering = + RenderExecutorTestAccess::AcquireRenderTargets( + executor, scheduler.Current(), &volume_color, 1, no_depth); + Require(name, "3D export bound exceeds depth", + volume_color.image_id == color.image_id && + volume_color.desc.info.extent == vk::Extent3D{32, 32, 32} && + volume_color.desc.info.data.size == allocation_size && + volume_color.desc.view_info.type == vk::ImageViewType::e2DArray && + volume_color.desc.view_info.base_layer == base_slice && + volume_color.desc.view_info.layer_count == 32 - base_slice && + volume_rendering.num_layers == 32 - base_slice && + registers.GetRenderTarget(0).view.last_array_slice_index == 32, + "3D export bounds changed the backing or exceeded its attachment depth"); + scheduler.Current().BeginRendering(volume_rendering); + scheduler.Current().EndRendering(); + } + RenderExecutorTestAccess::ResetBindings(executor); resources.UnmapMemory(base, allocation_size); scheduler.Finish();