Skip to content

Commit 6c55332

Browse files
committed
[vk] add support for rendering to slices of 3D textures
1 parent d100d33 commit 6c55332

File tree

5 files changed

+68
-20
lines changed

5 files changed

+68
-20
lines changed

tests/tests/wgpu-gpu/render_target.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use wgpu::{
22
util::{BufferInitDescriptor, DeviceExt},
33
vertex_attr_array,
44
};
5-
use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, TestingContext};
5+
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters, TestingContext};
66

77
#[gpu_test]
88
static DRAW_TO_2D_VIEW: GpuTestConfiguration = GpuTestConfiguration::new()
@@ -236,14 +236,10 @@ async fn run_test(
236236

237237
#[gpu_test]
238238
static DRAW_TO_3D_VIEW: GpuTestConfiguration = GpuTestConfiguration::new()
239-
.parameters(
240-
TestParameters::default()
241-
.limits(wgpu::Limits {
242-
max_texture_dimension_3d: 512,
243-
..wgpu::Limits::downlevel_webgl2_defaults()
244-
})
245-
.skip(FailureCase::backend(wgpu::Backends::VULKAN)),
246-
)
239+
.parameters(TestParameters::default().limits(wgpu::Limits {
240+
max_texture_dimension_3d: 512,
241+
..wgpu::Limits::downlevel_webgl2_defaults()
242+
}))
247243
.run_async(run_test_3d);
248244

249245
async fn run_test_3d(ctx: TestingContext) {

wgpu-core/src/device/resource.rs

-10
Original file line numberDiff line numberDiff line change
@@ -929,16 +929,6 @@ impl Device {
929929
desc.format,
930930
));
931931
}
932-
933-
// Renderable textures can only be 2D on Vulkan (until we implement 3D support)
934-
if self.backend() == wgt::Backend::Vulkan
935-
&& desc.usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT)
936-
{
937-
return Err(CreateTextureError::InvalidDimensionUsages(
938-
wgt::TextureUsages::RENDER_ATTACHMENT,
939-
desc.dimension,
940-
));
941-
}
942932
}
943933

944934
if desc.dimension != wgt::TextureDimension::D2

wgpu-hal/src/vulkan/command.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,31 @@ impl super::CommandEncoder {
7171
}
7272
})
7373
}
74+
75+
fn make_temp_texture_view(
76+
&mut self,
77+
key: super::TempTextureViewKey,
78+
) -> Result<vk::ImageView, crate::DeviceError> {
79+
Ok(match self.temp_texture_views.entry(key) {
80+
Entry::Occupied(e) => *e.get(),
81+
Entry::Vacant(e) => {
82+
let vk_info = vk::ImageViewCreateInfo::default()
83+
.image(e.key().texture)
84+
.view_type(vk::ImageViewType::TYPE_2D)
85+
.format(e.key().format)
86+
.subresource_range(vk::ImageSubresourceRange {
87+
aspect_mask: vk::ImageAspectFlags::COLOR,
88+
base_mip_level: e.key().mip_level,
89+
level_count: 1,
90+
base_array_layer: e.key().depth_slice,
91+
layer_count: 1,
92+
});
93+
let raw = unsafe { self.device.raw.create_image_view(&vk_info, None) }
94+
.map_err(super::map_host_device_oom_and_ioca_err)?;
95+
*e.insert(raw)
96+
}
97+
})
98+
}
7499
}
75100

76101
impl crate::CommandEncoder for super::CommandEncoder {
@@ -747,6 +772,18 @@ impl crate::CommandEncoder for super::CommandEncoder {
747772

748773
for cat in desc.color_attachments {
749774
if let Some(cat) = cat.as_ref() {
775+
let color_view = if cat.target.view.dimension == wgt::TextureViewDimension::D3 {
776+
let key = super::TempTextureViewKey {
777+
texture: cat.target.view.raw_texture,
778+
format: cat.target.view.raw_format,
779+
mip_level: cat.target.view.base_mip_level,
780+
depth_slice: cat.depth_slice.unwrap(),
781+
};
782+
self.make_temp_texture_view(key)?
783+
} else {
784+
cat.target.view.raw
785+
};
786+
750787
vk_clear_values.push(vk::ClearValue {
751788
color: unsafe { cat.make_vk_clear_color() },
752789
});
@@ -759,7 +796,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
759796
};
760797

761798
rp_key.colors.push(Some(color));
762-
fb_key.attachments.push(cat.target.view.raw);
799+
fb_key.attachments.push(color_view);
763800
if let Some(ref at) = cat.resolve_target {
764801
vk_clear_values.push(unsafe { mem::zeroed() });
765802
fb_key.attachments.push(at.view.raw);

wgpu-hal/src/vulkan/device.rs

+9
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,11 @@ impl super::Device {
640640
let copy_size = desc.copy_extent();
641641

642642
let mut raw_flags = vk::ImageCreateFlags::empty();
643+
if desc.dimension == wgt::TextureDimension::D3
644+
&& desc.usage.contains(wgt::TextureUses::COLOR_TARGET)
645+
{
646+
raw_flags |= vk::ImageCreateFlags::TYPE_2D_ARRAY_COMPATIBLE;
647+
}
643648
if desc.is_cube_compatible() {
644649
raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
645650
}
@@ -1287,10 +1292,13 @@ impl crate::Device for super::Device {
12871292
self.counters.texture_views.add(1);
12881293

12891294
Ok(super::TextureView {
1295+
raw_texture: texture.raw,
12901296
raw,
12911297
layers,
12921298
format: desc.format,
12931299
raw_format,
1300+
base_mip_level: desc.range.base_mip_level,
1301+
dimension: desc.dimension,
12941302
})
12951303
}
12961304
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
@@ -1387,6 +1395,7 @@ impl crate::Device for super::Device {
13871395
rpass_debug_marker_active: false,
13881396
end_of_pass_timer_query: None,
13891397
framebuffers: Default::default(),
1398+
temp_texture_views: Default::default(),
13901399
counters: Arc::clone(&self.counters),
13911400
})
13921401
}

wgpu-hal/src/vulkan/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -790,10 +790,13 @@ impl Texture {
790790

791791
#[derive(Debug)]
792792
pub struct TextureView {
793+
raw_texture: vk::Image,
793794
raw: vk::ImageView,
794795
layers: NonZeroU32,
795796
format: wgt::TextureFormat,
796797
raw_format: vk::Format,
798+
base_mip_level: u32,
799+
dimension: wgt::TextureViewDimension,
797800
}
798801

799802
impl crate::DynTextureView for TextureView {}
@@ -871,6 +874,14 @@ struct FramebufferKey {
871874
extent: wgt::Extent3d,
872875
}
873876

877+
#[derive(Clone, Eq, Hash, PartialEq)]
878+
struct TempTextureViewKey {
879+
texture: vk::Image,
880+
format: vk::Format,
881+
mip_level: u32,
882+
depth_slice: u32,
883+
}
884+
874885
pub struct CommandEncoder {
875886
raw: vk::CommandPool,
876887
device: Arc<DeviceShared>,
@@ -908,6 +919,7 @@ pub struct CommandEncoder {
908919
end_of_pass_timer_query: Option<(vk::QueryPool, u32)>,
909920

910921
framebuffers: FastHashMap<FramebufferKey, vk::Framebuffer>,
922+
temp_texture_views: FastHashMap<TempTextureViewKey, vk::ImageView>,
911923

912924
counters: Arc<wgt::HalCounters>,
913925
}
@@ -935,6 +947,10 @@ impl Drop for CommandEncoder {
935947
unsafe { self.device.raw.destroy_framebuffer(fb, None) };
936948
}
937949

950+
for (_, view) in self.temp_texture_views.drain() {
951+
unsafe { self.device.raw.destroy_image_view(view, None) };
952+
}
953+
938954
self.counters.command_encoders.sub(1);
939955
}
940956
}

0 commit comments

Comments
 (0)