mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[d3d12,metal,gl] add support for rendering to slices of 3D textures
This commit is contained in:
parent
15477b84a9
commit
d714e3d95a
@ -2,7 +2,7 @@ use wgpu::{
|
||||
util::{BufferInitDescriptor, DeviceExt},
|
||||
vertex_attr_array,
|
||||
};
|
||||
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters, TestingContext};
|
||||
use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, TestingContext};
|
||||
|
||||
#[gpu_test]
|
||||
static DRAW_TO_2D_VIEW: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
@ -233,3 +233,188 @@ async fn run_test(
|
||||
let succeeded = data.iter().all(|b| *b == u8::MAX);
|
||||
assert!(succeeded);
|
||||
}
|
||||
|
||||
#[gpu_test]
|
||||
static DRAW_TO_3D_VIEW: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.limits(wgpu::Limits {
|
||||
max_texture_dimension_3d: 512,
|
||||
..wgpu::Limits::downlevel_webgl2_defaults()
|
||||
})
|
||||
.skip(FailureCase::backend(wgpu::Backends::VULKAN)),
|
||||
)
|
||||
.run_async(run_test_3d);
|
||||
|
||||
async fn run_test_3d(ctx: TestingContext) {
|
||||
let vertex_buffer_content: &[f32; 12] = &[
|
||||
// Triangle 1
|
||||
-1.0, -1.0, // Bottom left
|
||||
1.0, 1.0, // Top right
|
||||
-1.0, 1.0, // Top left
|
||||
// Triangle 2
|
||||
-1.0, -1.0, // Bottom left
|
||||
1.0, -1.0, // Bottom right
|
||||
1.0, 1.0, // Top right
|
||||
];
|
||||
let vertex_buffer = ctx.device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(vertex_buffer_content),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let shader_src = "
|
||||
@vertex
|
||||
fn vs_main(@location(0) position: vec2f) -> @builtin(position) vec4f {
|
||||
return vec4f(position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main() -> @location(0) vec4f {
|
||||
return vec4f(1.0);
|
||||
}
|
||||
";
|
||||
|
||||
let shader = ctx
|
||||
.device
|
||||
.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
source: wgpu::ShaderSource::Wgsl(shader_src.into()),
|
||||
});
|
||||
|
||||
let pipeline_desc = wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
layout: None,
|
||||
vertex: wgpu::VertexState {
|
||||
buffers: &[wgpu::VertexBufferLayout {
|
||||
array_stride: 8,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float32x2],
|
||||
}],
|
||||
module: &shader,
|
||||
entry_point: Some("vs_main"),
|
||||
compilation_options: Default::default(),
|
||||
},
|
||||
primitive: wgpu::PrimitiveState::default(),
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: Some("fs_main"),
|
||||
compilation_options: Default::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: wgpu::TextureFormat::R8Unorm,
|
||||
blend: None,
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
multiview: None,
|
||||
cache: None,
|
||||
};
|
||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||
|
||||
const SIZE: u32 = 512;
|
||||
const DEPTH: u32 = 2;
|
||||
const MIPS: u32 = 2;
|
||||
const fn size_for_mips(mips: u32) -> u64 {
|
||||
let mut out: u64 = 0;
|
||||
let mut mip = 0;
|
||||
while mip < mips {
|
||||
let size = SIZE as u64 >> mip;
|
||||
let z = DEPTH as u64 >> mip;
|
||||
out += size * size * z;
|
||||
|
||||
mip += 1;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
let out_texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: SIZE,
|
||||
height: SIZE,
|
||||
depth_or_array_layers: DEPTH,
|
||||
},
|
||||
mip_level_count: MIPS,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D3,
|
||||
format: wgpu::TextureFormat::R8Unorm,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[],
|
||||
});
|
||||
|
||||
let readback_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: size_for_mips(MIPS),
|
||||
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let mut encoder = ctx
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||
|
||||
for mip in 0..MIPS {
|
||||
let out_texture_view = out_texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
base_mip_level: mip,
|
||||
mip_level_count: Some(1),
|
||||
..Default::default()
|
||||
});
|
||||
for layer in 0..DEPTH >> mip {
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &out_texture_view,
|
||||
depth_slice: Some(layer),
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
rpass.set_pipeline(&pipeline);
|
||||
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
||||
rpass.draw(0..6, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
for mip in 0..MIPS {
|
||||
encoder.copy_texture_to_buffer(
|
||||
wgpu::TexelCopyTextureInfo {
|
||||
texture: &out_texture,
|
||||
mip_level: mip,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
},
|
||||
wgpu::TexelCopyBufferInfo {
|
||||
buffer: &readback_buffer,
|
||||
layout: wgpu::TexelCopyBufferLayout {
|
||||
offset: size_for_mips(mip),
|
||||
bytes_per_row: Some(SIZE >> mip),
|
||||
rows_per_image: Some(SIZE >> mip),
|
||||
},
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: SIZE >> mip,
|
||||
height: SIZE >> mip,
|
||||
depth_or_array_layers: DEPTH >> mip,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ctx.queue.submit([encoder.finish()]);
|
||||
|
||||
let slice = readback_buffer.slice(..);
|
||||
slice.map_async(wgpu::MapMode::Read, |_| ());
|
||||
|
||||
ctx.async_poll(wgpu::PollType::wait()).await.unwrap();
|
||||
|
||||
let data = slice.get_mapped_range();
|
||||
let succeeded = data.iter().all(|b| *b == u8::MAX);
|
||||
assert!(succeeded);
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::command::{
|
||||
};
|
||||
use crate::init_tracker::BufferInitTrackerAction;
|
||||
use crate::pipeline::{RenderPipeline, VertexStep};
|
||||
use crate::resource::InvalidResourceError;
|
||||
use crate::resource::{InvalidResourceError, ResourceErrorIdent};
|
||||
use crate::snatch::SnatchGuard;
|
||||
use crate::{
|
||||
api_log,
|
||||
@ -621,6 +621,18 @@ pub enum ColorAttachmentError {
|
||||
TooMany { given: usize, limit: usize },
|
||||
#[error("The total number of bytes per sample in color attachments {total} exceeds the limit {limit}")]
|
||||
TooManyBytesPerSample { total: u32, limit: u32 },
|
||||
#[error("Depth slice must be less than {limit} but is {given}")]
|
||||
DepthSliceLimit { given: u32, limit: u32 },
|
||||
#[error("Color attachment's view is 3D and requires depth slice to be provided")]
|
||||
MissingDepthSlice,
|
||||
#[error("Depth slice was provided but the color attachment's view is not 3D")]
|
||||
UnneededDepthSlice,
|
||||
#[error("{view}'s subresource at mip {mip_level} and depth/array layer {depth_or_array_layer} is already attached to this render pass")]
|
||||
SubresourceOverlap {
|
||||
view: ResourceErrorIdent,
|
||||
mip_level: u32,
|
||||
depth_or_array_layer: u32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
@ -1096,6 +1108,8 @@ impl<'d> RenderPassInfo<'d> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut attachment_set = crate::FastHashSet::default();
|
||||
|
||||
let mut color_attachments_hal =
|
||||
ArrayVec::<Option<hal::ColorAttachment<_>>, { hal::MAX_COLOR_ATTACHMENTS }>::new();
|
||||
for (index, attachment) in color_attachments.iter().enumerate() {
|
||||
@ -1126,6 +1140,71 @@ impl<'d> RenderPassInfo<'d> {
|
||||
));
|
||||
}
|
||||
|
||||
if color_view.desc.dimension == TextureViewDimension::D3 {
|
||||
if let Some(depth_slice) = at.depth_slice {
|
||||
let mip = color_view.desc.range.base_mip_level;
|
||||
let mip_size = color_view
|
||||
.parent
|
||||
.desc
|
||||
.size
|
||||
.mip_level_size(mip, color_view.parent.desc.dimension);
|
||||
let limit = mip_size.depth_or_array_layers;
|
||||
if depth_slice >= limit {
|
||||
return Err(RenderPassErrorInner::ColorAttachment(
|
||||
ColorAttachmentError::DepthSliceLimit {
|
||||
given: depth_slice,
|
||||
limit,
|
||||
},
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(RenderPassErrorInner::ColorAttachment(
|
||||
ColorAttachmentError::MissingDepthSlice,
|
||||
));
|
||||
}
|
||||
} else if at.depth_slice.is_some() {
|
||||
return Err(RenderPassErrorInner::ColorAttachment(
|
||||
ColorAttachmentError::UnneededDepthSlice,
|
||||
));
|
||||
}
|
||||
|
||||
fn check_attachment_overlap(
|
||||
attachment_set: &mut crate::FastHashSet<(crate::track::TrackerIndex, u32, u32)>,
|
||||
view: &TextureView,
|
||||
depth_slice: Option<u32>,
|
||||
) -> Result<(), ColorAttachmentError> {
|
||||
let mut insert = |slice| {
|
||||
let mip_level = view.desc.range.base_mip_level;
|
||||
if attachment_set.insert((view.tracking_data.tracker_index(), mip_level, slice))
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ColorAttachmentError::SubresourceOverlap {
|
||||
view: view.error_ident(),
|
||||
mip_level,
|
||||
depth_or_array_layer: slice,
|
||||
})
|
||||
}
|
||||
};
|
||||
match view.desc.dimension {
|
||||
TextureViewDimension::D2 => {
|
||||
insert(view.desc.range.base_array_layer)?;
|
||||
}
|
||||
TextureViewDimension::D2Array => {
|
||||
for layer in view.selector.layers.clone() {
|
||||
insert(layer)?;
|
||||
}
|
||||
}
|
||||
TextureViewDimension::D3 => {
|
||||
insert(depth_slice.unwrap())?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
check_attachment_overlap(&mut attachment_set, color_view, at.depth_slice)?;
|
||||
|
||||
Self::add_pass_texture_init_actions(
|
||||
at.load_op,
|
||||
at.store_op,
|
||||
@ -1141,6 +1220,8 @@ impl<'d> RenderPassInfo<'d> {
|
||||
resolve_view.same_device(device)?;
|
||||
check_multiview(resolve_view)?;
|
||||
|
||||
check_attachment_overlap(&mut attachment_set, resolve_view, None)?;
|
||||
|
||||
let resolve_location = AttachmentErrorLocation::Color {
|
||||
index,
|
||||
resolve: true,
|
||||
|
||||
@ -929,8 +929,11 @@ impl Device {
|
||||
desc.format,
|
||||
));
|
||||
}
|
||||
// Renderable textures can only be 2D
|
||||
if desc.usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) {
|
||||
|
||||
// Renderable textures can only be 2D on Vulkan (until we implement 3D support)
|
||||
if self.backend() == wgt::Backend::Vulkan
|
||||
&& desc.usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT)
|
||||
{
|
||||
return Err(CreateTextureError::InvalidDimensionUsages(
|
||||
wgt::TextureUsages::RENDER_ATTACHMENT,
|
||||
desc.dimension,
|
||||
@ -948,6 +951,14 @@ impl Device {
|
||||
desc.format,
|
||||
));
|
||||
}
|
||||
|
||||
// Renderable textures can only be 2D or 3D
|
||||
if desc.usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) {
|
||||
return Err(CreateTextureError::InvalidDimensionUsages(
|
||||
wgt::TextureUsages::RENDER_ATTACHMENT,
|
||||
desc.dimension,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if desc.format.is_compressed() {
|
||||
@ -1124,17 +1135,13 @@ impl Device {
|
||||
|
||||
let clear_mode = if hal_usage
|
||||
.intersects(wgt::TextureUses::DEPTH_STENCIL_WRITE | wgt::TextureUses::COLOR_TARGET)
|
||||
&& desc.dimension == wgt::TextureDimension::D2
|
||||
{
|
||||
let (is_color, usage) = if desc.format.is_depth_stencil_format() {
|
||||
(false, wgt::TextureUses::DEPTH_STENCIL_WRITE)
|
||||
} else {
|
||||
(true, wgt::TextureUses::COLOR_TARGET)
|
||||
};
|
||||
let dimension = match desc.dimension {
|
||||
wgt::TextureDimension::D1 => TextureViewDimension::D1,
|
||||
wgt::TextureDimension::D2 => TextureViewDimension::D2,
|
||||
wgt::TextureDimension::D3 => unreachable!(),
|
||||
};
|
||||
|
||||
let clear_label = hal_label(
|
||||
Some("(wgpu internal) clear texture view"),
|
||||
@ -1149,7 +1156,7 @@ impl Device {
|
||||
let desc = hal::TextureViewDescriptor {
|
||||
label: clear_label,
|
||||
format: $format,
|
||||
dimension,
|
||||
dimension: TextureViewDimension::D2,
|
||||
usage,
|
||||
range: wgt::ImageSubresourceRange {
|
||||
aspect: $aspect,
|
||||
@ -1420,9 +1427,12 @@ impl Device {
|
||||
break 'error Err(TextureViewNotRenderableReason::Usage(resolved_usage));
|
||||
}
|
||||
|
||||
if !(resolved_dimension == TextureViewDimension::D2
|
||||
|| resolved_dimension == TextureViewDimension::D2Array)
|
||||
{
|
||||
let allowed_view_dimensions = [
|
||||
TextureViewDimension::D2,
|
||||
TextureViewDimension::D2Array,
|
||||
TextureViewDimension::D3,
|
||||
];
|
||||
if !allowed_view_dimensions.contains(&resolved_dimension) {
|
||||
break 'error Err(TextureViewNotRenderableReason::Dimension(
|
||||
resolved_dimension,
|
||||
));
|
||||
|
||||
@ -73,6 +73,13 @@ impl Drop for super::CommandEncoder {
|
||||
fn drop(&mut self) {
|
||||
use crate::CommandEncoder;
|
||||
unsafe { self.discard_encoding() }
|
||||
|
||||
let mut rtv_pool = self.rtv_pool.lock();
|
||||
for handle in self.temp_rtv_handles.drain(..) {
|
||||
rtv_pool.free_handle(handle);
|
||||
}
|
||||
drop(rtv_pool);
|
||||
|
||||
self.counters.command_encoders.sub(1);
|
||||
}
|
||||
}
|
||||
@ -762,13 +769,39 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
|
||||
let mut color_views =
|
||||
[Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS];
|
||||
let mut rtv_pool = self.rtv_pool.lock();
|
||||
for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) {
|
||||
if let Some(cat) = cat.as_ref() {
|
||||
*rtv = cat.target.view.handle_rtv.unwrap().raw;
|
||||
if cat.target.view.dimension == wgt::TextureViewDimension::D3 {
|
||||
let desc = Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC {
|
||||
Format: cat.target.view.raw_format,
|
||||
ViewDimension: Direct3D12::D3D12_RTV_DIMENSION_TEXTURE3D,
|
||||
Anonymous: Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC_0 {
|
||||
Texture3D: Direct3D12::D3D12_TEX3D_RTV {
|
||||
MipSlice: cat.target.view.mip_slice,
|
||||
FirstWSlice: cat.depth_slice.unwrap(),
|
||||
WSize: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
let handle = rtv_pool.alloc_handle()?;
|
||||
unsafe {
|
||||
self.device.CreateRenderTargetView(
|
||||
&cat.target.view.texture,
|
||||
Some(&desc),
|
||||
handle.raw,
|
||||
)
|
||||
};
|
||||
*rtv = handle.raw;
|
||||
self.temp_rtv_handles.push(handle);
|
||||
} else {
|
||||
*rtv = cat.target.view.handle_rtv.unwrap().raw;
|
||||
}
|
||||
} else {
|
||||
*rtv = self.null_rtv_handle.raw;
|
||||
}
|
||||
}
|
||||
drop(rtv_pool);
|
||||
|
||||
let ds_view = desc.depth_stencil_attachment.as_ref().map(|ds| {
|
||||
if ds.target.usage == wgt::TextureUses::DEPTH_STENCIL_WRITE {
|
||||
@ -803,8 +836,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
}
|
||||
if let Some(ref target) = cat.resolve_target {
|
||||
self.pass.resolves.push(super::PassResolve {
|
||||
src: cat.target.view.target_base.clone(),
|
||||
dst: target.view.target_base.clone(),
|
||||
src: (
|
||||
cat.target.view.texture.clone(),
|
||||
cat.target.view.subresource_index,
|
||||
),
|
||||
dst: (target.view.texture.clone(), target.view.subresource_index),
|
||||
format: target.view.raw_format,
|
||||
});
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ impl super::Device {
|
||||
},
|
||||
features,
|
||||
shared: Arc::new(shared),
|
||||
rtv_pool: Mutex::new(rtv_pool),
|
||||
rtv_pool: Arc::new(Mutex::new(rtv_pool)),
|
||||
dsv_pool: Mutex::new(descriptor::CpuPool::new(
|
||||
raw.clone(),
|
||||
Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
|
||||
@ -539,10 +539,14 @@ impl crate::Device for super::Device {
|
||||
Ok(super::TextureView {
|
||||
raw_format: view_desc.rtv_dsv_format,
|
||||
aspects: view_desc.aspects,
|
||||
target_base: (
|
||||
texture.resource.clone(),
|
||||
texture.calc_subresource(desc.range.base_mip_level, desc.range.base_array_layer, 0),
|
||||
dimension: desc.dimension,
|
||||
texture: texture.resource.clone(),
|
||||
subresource_index: texture.calc_subresource(
|
||||
desc.range.base_mip_level,
|
||||
desc.range.base_array_layer,
|
||||
0,
|
||||
),
|
||||
mip_slice: desc.range.base_mip_level,
|
||||
handle_srv: if desc.usage.intersects(wgt::TextureUses::RESOURCE) {
|
||||
match unsafe { view_desc.to_srv() } {
|
||||
Some(raw_desc) => {
|
||||
@ -584,7 +588,10 @@ impl crate::Device for super::Device {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
handle_rtv: if desc.usage.intersects(wgt::TextureUses::COLOR_TARGET) {
|
||||
handle_rtv: if desc.usage.intersects(wgt::TextureUses::COLOR_TARGET)
|
||||
&& desc.dimension != wgt::TextureViewDimension::D3
|
||||
// 3D RTVs must be created in the render pass
|
||||
{
|
||||
let raw_desc = unsafe { view_desc.to_rtv() };
|
||||
let handle = self.rtv_pool.lock().alloc_handle()?;
|
||||
unsafe {
|
||||
@ -725,6 +732,8 @@ impl crate::Device for super::Device {
|
||||
device: self.raw.clone(),
|
||||
shared: Arc::clone(&self.shared),
|
||||
mem_allocator: self.mem_allocator.clone(),
|
||||
rtv_pool: Arc::clone(&self.rtv_pool),
|
||||
temp_rtv_handles: Vec::new(),
|
||||
null_rtv_handle: self.null_rtv_handle,
|
||||
list: None,
|
||||
free_lists: Vec::new(),
|
||||
|
||||
@ -646,7 +646,7 @@ pub struct Device {
|
||||
features: wgt::Features,
|
||||
shared: Arc<DeviceShared>,
|
||||
// CPU only pools
|
||||
rtv_pool: Mutex<descriptor::CpuPool>,
|
||||
rtv_pool: Arc<Mutex<descriptor::CpuPool>>,
|
||||
dsv_pool: Mutex<descriptor::CpuPool>,
|
||||
srv_uav_pool: Mutex<descriptor::CpuPool>,
|
||||
// library
|
||||
@ -798,6 +798,9 @@ pub struct CommandEncoder {
|
||||
shared: Arc<DeviceShared>,
|
||||
mem_allocator: Allocator,
|
||||
|
||||
rtv_pool: Arc<Mutex<descriptor::CpuPool>>,
|
||||
temp_rtv_handles: Vec<descriptor::Handle>,
|
||||
|
||||
null_rtv_handle: descriptor::Handle,
|
||||
list: Option<Direct3D12::ID3D12GraphicsCommandList>,
|
||||
free_lists: Vec<Direct3D12::ID3D12GraphicsCommandList>,
|
||||
@ -918,8 +921,10 @@ impl Texture {
|
||||
pub struct TextureView {
|
||||
raw_format: Dxgi::Common::DXGI_FORMAT,
|
||||
aspects: crate::FormatAspects,
|
||||
/// only used by resolve
|
||||
target_base: (Direct3D12::ID3D12Resource, u32),
|
||||
dimension: wgt::TextureViewDimension,
|
||||
texture: Direct3D12::ID3D12Resource,
|
||||
subresource_index: u32,
|
||||
mip_slice: u32,
|
||||
handle_srv: Option<descriptor::Handle>,
|
||||
handle_uav: Option<descriptor::Handle>,
|
||||
handle_rtv: Option<descriptor::Handle>,
|
||||
|
||||
@ -250,16 +250,10 @@ impl ViewDescriptor {
|
||||
PlaneSlice: aspects_to_plane(self.aspects),
|
||||
}
|
||||
}
|
||||
wgt::TextureViewDimension::D3 => {
|
||||
desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE3D;
|
||||
desc.Anonymous.Texture3D = Direct3D12::D3D12_TEX3D_RTV {
|
||||
MipSlice: self.mip_level_base,
|
||||
FirstWSlice: self.array_layer_base,
|
||||
WSize: self.array_layer_count,
|
||||
}
|
||||
}
|
||||
wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => {
|
||||
panic!("Unable to view texture as cube RTV")
|
||||
wgt::TextureViewDimension::D3
|
||||
| wgt::TextureViewDimension::Cube
|
||||
| wgt::TextureViewDimension::CubeArray => {
|
||||
panic!("Unable to view texture as cube or 3D RTV")
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,7 +331,7 @@ impl ViewDescriptor {
|
||||
wgt::TextureViewDimension::D3
|
||||
| wgt::TextureViewDimension::Cube
|
||||
| wgt::TextureViewDimension::CubeArray => {
|
||||
panic!("Unable to view texture as cube or 3D RTV")
|
||||
panic!("Unable to view texture as cube or 3D DSV")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -557,6 +557,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
self.cmd_buffer.commands.push(C::BindAttachment {
|
||||
attachment,
|
||||
view: cat.target.view.clone(),
|
||||
depth_slice: cat.depth_slice,
|
||||
});
|
||||
if let Some(ref rat) = cat.resolve_target {
|
||||
self.state
|
||||
@ -578,6 +579,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
self.cmd_buffer.commands.push(C::BindAttachment {
|
||||
attachment,
|
||||
view: dsat.target.view.clone(),
|
||||
depth_slice: None,
|
||||
});
|
||||
if aspects.contains(crate::FormatAspects::DEPTH)
|
||||
&& !dsat.depth_ops.contains(crate::AttachmentOps::STORE)
|
||||
|
||||
@ -902,6 +902,7 @@ enum Command {
|
||||
BindAttachment {
|
||||
attachment: u32,
|
||||
view: TextureView,
|
||||
depth_slice: Option<u32>,
|
||||
},
|
||||
ResolveAttachment {
|
||||
attachment: u32,
|
||||
|
||||
@ -98,6 +98,7 @@ impl super::Queue {
|
||||
fbo_target: u32,
|
||||
attachment: u32,
|
||||
view: &super::TextureView,
|
||||
depth_slice: Option<u32>,
|
||||
) {
|
||||
match view.inner {
|
||||
super::TextureInner::Renderbuffer { raw } => {
|
||||
@ -126,13 +127,18 @@ impl super::Queue {
|
||||
)
|
||||
};
|
||||
} else if is_layered_target(target) {
|
||||
let layer = if target == glow::TEXTURE_3D {
|
||||
depth_slice.unwrap() as i32
|
||||
} else {
|
||||
view.array_layers.start as i32
|
||||
};
|
||||
unsafe {
|
||||
gl.framebuffer_texture_layer(
|
||||
fbo_target,
|
||||
attachment,
|
||||
Some(raw),
|
||||
view.mip_levels.start as i32,
|
||||
view.array_layers.start as i32,
|
||||
layer,
|
||||
)
|
||||
};
|
||||
} else {
|
||||
@ -1096,8 +1102,11 @@ impl super::Queue {
|
||||
C::BindAttachment {
|
||||
attachment,
|
||||
ref view,
|
||||
depth_slice,
|
||||
} => {
|
||||
unsafe { self.set_attachment(gl, glow::DRAW_FRAMEBUFFER, attachment, view) };
|
||||
unsafe {
|
||||
self.set_attachment(gl, glow::DRAW_FRAMEBUFFER, attachment, view, depth_slice)
|
||||
};
|
||||
}
|
||||
C::ResolveAttachment {
|
||||
attachment,
|
||||
@ -1108,7 +1117,13 @@ impl super::Queue {
|
||||
unsafe { gl.read_buffer(attachment) };
|
||||
unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.copy_fbo)) };
|
||||
unsafe {
|
||||
self.set_attachment(gl, glow::DRAW_FRAMEBUFFER, glow::COLOR_ATTACHMENT0, dst)
|
||||
self.set_attachment(
|
||||
gl,
|
||||
glow::DRAW_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
dst,
|
||||
None,
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
gl.blit_framebuffer(
|
||||
|
||||
@ -532,6 +532,9 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
if let Some(at) = at.as_ref() {
|
||||
let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap();
|
||||
at_descriptor.set_texture(Some(&at.target.view.raw));
|
||||
if let Some(depth_slice) = at.depth_slice {
|
||||
at_descriptor.set_depth_plane(depth_slice as u64);
|
||||
}
|
||||
if let Some(ref resolve) = at.resolve_target {
|
||||
//Note: the selection of levels and slices is already handled by `TextureView`
|
||||
at_descriptor.set_resolve_texture(Some(&resolve.view.raw));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user