-
Notifications
You must be signed in to change notification settings - Fork 543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ll][WIP] Encoding and state transitions #1502
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great to see, awesome stuff @Bastacyclop !
PR is obviously WIP, and I'd like the API to change a bit. Looking forward to see it merged ;)
image_extent: d::Extent { width, height, depth: 1 }, | ||
}]); | ||
|
||
let init_submit = init_encoder.finish(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I'm worried about: passing the encoder in the device creation doesn't make it safe: user is still responsible to actually submit it. So I think we should change to tokens right away:
- resource creation returns a token
- encoder can do
init_resources(&[Token])
, which consumes the tokens.
This is not safer but I believe is more universal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's also better for batching into a single barrier command :)
src/render/src/buffer.rs
Outdated
} | ||
|
||
impl<B: Backend> handle::raw::Buffer<B> { | ||
pub fn stable_state(&self) -> core::buffer::State { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub(crate)
?
src/render/src/device.rs
Outdated
usage: image::Usage, | ||
kind: image::Kind, | ||
mip_levels: image::Level, | ||
format: format::Format | ||
) -> Result<handle::raw::Image<B>, image::CreationError> | ||
where A: Allocator<B> | ||
where A: Allocator<B>, | ||
C: core::queue::Supports<core::Transfer> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uh, yeah, that certainly looks out of place here. Device shouldn't know anything about queues and their capabilities
@@ -84,6 +90,41 @@ pub struct Submit<B: Backend, C> { | |||
pub(crate) pool: PoolDependency<B, C> | |||
} | |||
|
|||
// TODO: coalescing? | |||
struct ImageStates { | |||
states: Vec<core::image::State>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could probably just add the level/slice into the hashmap key instead of introducing this struct.
Do you think the struct gives us an advantage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if it would be worth it to coalesce the state slices instead of always having a state for each level/layer. Otherwise, I don't see any advantage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let's have it this way for now, will reconsider later.
src/render/src/encoder.rs
Outdated
) { | ||
let mut barriers = Vec::new(); | ||
for &(buffer, state) in buffer_states { | ||
self.require_buffer_state(buffer, state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could be barriers.extend(self.require_buffer_state(...));
src/render/src/encoder.rs
Outdated
info.zoffset + info.depth] | ||
}); | ||
for &(image, (level, layer), state) in image_states { | ||
self.require_image_state(image, level, layer, state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
src/render/src/encoder.rs
Outdated
} | ||
let current_stage = mem::replace(&mut self.pipeline_stage, stage); | ||
if (current_stage != stage) || !barriers.is_empty() { | ||
println!("barrier: {:?}, {:?}", current_stage..stage, &barriers[..]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please change to debug!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you will want to keep it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removing works too, I don't mind either way
src/render/src/image.rs
Outdated
pub fn to_raw_image_info(&self, mip: Level) -> RawImageInfo { | ||
self.to_image_info(mip).convert(self.format) | ||
impl<B: Backend> handle::raw::Image<B> { | ||
pub fn stable_state(&self) -> core::image::State { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should store this as a constant instead of recomputing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A constant like a field in Info
, or something more global ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, a field in Info
would work
0c53fca
to
7803718
Compare
examples/render/quad_render/main.rs
Outdated
@@ -36,6 +37,13 @@ const QUAD: [Vertex; 6] = [ | |||
Vertex { a_Pos: [ -0.5,-0.33 ], a_Uv: [0.0, 0.0] }, | |||
]; | |||
|
|||
gfx_descriptor_struct! { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yammy!
examples/render/quad_render/main.rs
Outdated
stage_flags: pso::STAGE_FRAGMENT, | ||
} | ||
], | ||
gfx_allocate_descriptor_structs!(context.mut_device(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, not sure why this has to be a macro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you allocate a (potential) batch of descriptor structs, the result can consist of different types and cannot be a vector (unless dynamically typed). We could probably have some tricky tuple imbrication using a builder but it seems worse to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also come up with another descriptor allocation API, obviously. It seemed like an easy way to avoid explicit pools while still allowing some batching.
src/render/src/device.rs
Outdated
#[doc(hidden)] | ||
pub fn allocate_descriptor_sets( | ||
&mut self, | ||
sets_bindings: &[&[core::pso::DescriptorSetLayoutBinding]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this a 2d array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can allocate multiple sets in a single batch, allowing to share the underlying descriptor pool.
examples/render/quad_render/main.rs
Outdated
let extent = d::Extent { width: pixel_width as _, height: pixel_height as _, depth: 1 }; | ||
device.create_framebuffer(&render_pass, &[frame_rtv], &[], extent) | ||
device.create_framebuffer(pipeline.render_pass(), &[rtv.resource()], &[], extent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if you have planned it but how difficult would you estimate to add custom renderpass support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think about it yet, I'm focusing on getting simple pipelines working for this PR.
examples/render/quad_render/main.rs
Outdated
}, | ||
]); | ||
context.mut_device().update_descriptor_sets() | ||
.write(sample_desc.sampled_image(), 0, vec![&image_srv]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need vec![..]
here?
examples/render/quad_render/main.rs
Outdated
} | ||
|
||
submits.push(encoder.finish()); | ||
context.present(mem::replace(&mut submits, Vec::new())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, do we have alternatives here? drain(..)
or sth like this?
examples/render/quad_render/main.rs
Outdated
} | ||
|
||
println!("cleanup!"); | ||
device.destroy_descriptor_pool(srv_pool); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
praise the garbage collector \o/
src/render/src/macros.rs
Outdated
}; | ||
|
||
// TODO: | ||
let dependency = cpass::SubpassDependency { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vulkan's spec (and probably we also) implicitly add subpass dependencies from EXTERNAl -> firstSubpass and lastSubpass -> EXTERNAL, which should cover your use-case also. So this dependencies shouldn't be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it's shaping up, great! The trait magic will need to be reviewed again carefully.
examples/render/quad_render/main.rs
Outdated
let sample_desc = context.mut_device().create_descriptors(1).pop().unwrap(); | ||
let pipe_init = pipe::Init { | ||
sample: &sample_desc, | ||
color: pso::ColorInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason not to use any of the draw_state::preset::blend
things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason, I simply kept the original code here.
examples/render/quad_render/main.rs
Outdated
element: pso::Element { | ||
format: <Vec2<f32> as Formatted>::get_format(), | ||
offset: 0, | ||
let sample_desc = context.mut_device().create_descriptors(1).pop().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are the mut_device
calls final or temporary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do let mut device = context.ref_device().clone();
at the beginning.
examples/render/quad_render/main.rs
Outdated
write: pso::DescriptorWrite::Sampler(vec![sampler.resource()]), | ||
}, | ||
]); | ||
context.mut_device().update_descriptor_sets() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great 👍
examples/render/quad_render/main.rs
Outdated
}, | ||
]); | ||
context.mut_device().update_descriptor_sets() | ||
.write(sample_desc.sampled_image(), 0, vec![&image_srv]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure why you'd want to have vec![]
here as opposed to &[]
though
examples/render/quad_render/main.rs
Outdated
@@ -344,15 +265,15 @@ fn main() { | |||
|
|||
cmd_buffer.set_viewports(&[viewport]); | |||
cmd_buffer.set_scissors(&[scissor]); | |||
cmd_buffer.bind_graphics_pipeline(&pipelines[0].as_ref().unwrap()); | |||
cmd_buffer.bind_graphics_pipeline(pipeline.pipeline()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uh? pipeline.pipeline
doesn't sound good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that should not stay once encoder.draw
is done :p
src/render/src/device.rs
Outdated
{ | ||
use core::DescriptorPool as CDP; | ||
|
||
let bindings = &D::layout_bindings()[..]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like a case for associated constants here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem is I can't make a &'static
slice without macro tricks to get the binding index (maybe easier with a custom derive ?).
src/render/src/device.rs
Outdated
|
||
let bindings = &D::layout_bindings()[..]; | ||
let layout = self.create_descriptor_set_layout(bindings); | ||
let mut ranges = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idiomatic way to do this would be let ranges = bindigns.iter().map(...).collect::<Vec<_>>()
src/render/src/pso/mod.rs
Outdated
} | ||
} | ||
pub trait Bind { | ||
fn desc_type() -> core::pso::DescriptorType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
associated constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff!
examples/render/quad_render/main.rs
Outdated
sampled_image: gfx::pso::SampledImage, | ||
sampler: gfx::pso::Sampler, | ||
} | ||
} | ||
|
||
gfx_graphics_pipeline! { | ||
pipe { | ||
sample: gfx::pso::DescriptorSet<SampleDesc<B>>, // TODO remove <B> | ||
desc: gfx::pso::DescriptorSet<desc::Set<B>>, // TODO: improve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we still do need to get rid of B
here since no other PSO component is backend dependent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The macro could generate a desc::Component
, how does that sound ?
src/render/src/device.rs
Outdated
let buffer = self.raw.create_framebuffer( | ||
pipeline.render_pass(), &rtv_res[..], &dsv_res[..], extent); | ||
let info = handle::FrameBufferInfo { | ||
rtvs: rtvs.iter().map(|&rtv| rtv.clone()).collect(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could just have used rtvs.iter().cloned().collect()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would require cloned().cloned()
because this is a &&RTV
.
src/render/src/encoder.rs
Outdated
self.command_buffer.bind_samplers(&self.raw_pso_data.samplers); | ||
self.draw_slice(slice, slice.instances); | ||
// TODO: instances | ||
data.begin_renderpass(self, pipeline).draw(vertices, 0..1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
starting and ending a render pas for each draw call is not perfect.
I think one way we cold make this nicer is to have encoders behave in the same way they do in Metal (it is a nice API, no matter what political negativity is around it):
- have command buffers visible to the user
- user creates a graphics encoder, which starts a render pass given the targets, and borrows the command buffer mutably
- user submits a bunch of gaphics/draw commands
- user drops the encoder, which ends the render pass and releases the command buffer borrow, which can now be submitted
cc @msiglreith
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be totally happy if we can get a Metal-ish API, but I also see why you went with the renderpass for each pipeline approach. Sounds like a hard problem due to required compatibility between framebuffer, pipeline and renderpass.
We might have to dynamically compile renderpasses (with single renderpass) and pipelines here to get this working or require the user to do it upfront or a mix of the both approaches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I see it:
- user declares a render pass using a macro, like the other things. The information required for the macro is exactly what Vulkan considers to not be a part of render pass compatibility.
- the "compatible" pieces would then be supplied at run-time during render pass creation by the user
- the pipeline definition would then point to a render pass definition, thus statically enforcing which pipelines are going to be accepted in the graphics encoder corresponding to the given render pass definition (not the instance)
Does it make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable even though I'm unsure if it's that easy to split the renderpass definition in compatible and non-compatible parts..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice but I think it deserves a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's fair
src/render/src/handle.rs
Outdated
@@ -230,7 +231,7 @@ define_resources! { | |||
PipelineLayout: (), | |||
GraphicsPipeline: (), | |||
// ComputePipeline | |||
// FrameBuffer | |||
FrameBuffer: ::handle::FrameBufferInfo<B>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would be nicer to not use global imports
let mut binding = 0; | ||
let mut next_binding = || {let b = binding; binding += 1; b }; | ||
(Set { | ||
$( $field: next_binding(), )* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: heh, not sure what we are getting by moving next_binding()
up as opposed to just inlining it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we avoid getting a warning for the last unused +=
operation.
src/render/src/pso/mod.rs
Outdated
fn desc_type() -> core::pso::DescriptorType; | ||
fn desc_count() -> usize; | ||
pub trait BindDesc { | ||
const TYPE: core::pso::DescriptorType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
niiice!
src/render/src/encoder.rs
Outdated
-> core::memory::Barrier<'b, B> | ||
{ | ||
let creation_state = (core::image::Access::empty(), ImageLayout::Undefined); | ||
let levels = image.info().kind.get_num_levels(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this does not give the actual image levels, should I use image.info().mip_levels
instead ?.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect them to match, plus minus the differences between 0 and 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I see it, kind.get_num_levels()
is how many mip levels you should have if you had mip mapping while info().mip_levels
is how many mip levels you really have (so it is valid even if you do not have mip mapping).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you just need to remove Info::mip_levels
completely. Image Kind
is the full description of what an image has in terms of dimensions/levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we agree that:
- You can have images with arbitrary mip levels (1 most likely, like for backbuffers).
kind.get_num_levels()
will not return this number, but rather(1..).find(|level| dominant>>level <= 1).unwrap()
, which is like the maximum number of mip levels you can have.
And that we need the actual level count and not the maximum level count ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Bastacyclop Sorry, I got confused. Used the get_num_layers
lately and assumed get_num_levels
does a similar thing. You are correct, it doesn't return the actually stored mipmap count, this method can only be used for estimation during the image creation, and is rather pointless afterwards.
So in your case using image.info().mip_levels
is the way to proceed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is quite a few rough points, we'll surely need to spend more time polishing this out. The core of the PR is good though, just a few things before we proceed.
desc: &desc, | ||
color: pso::ColorInfo { | ||
mask: state::MASK_ALL, | ||
color: Some(state::BlendChannel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's use the presets. We can do as a follow-up
vertices: (), | ||
}; | ||
let pipeline = device.create_graphics_pipeline( | ||
pso::GraphicsShaderSet { | ||
vertex: pso::EntryPoint { entry: "main", module: &vs_module }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you know what would be really cool? to write:
vertex: vs_module["main"],
|
||
context.mut_device() | ||
.write_mapping(&vertex_buffer, 0..vertex_count) | ||
device.write_mapping(&vertex_buffer, 0..vertex_count) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if you can actually do anything with that buffer, including the mapping, before it's initialized. E.g. doesn't Vulkan require the HOST access to be set?
|
||
println!("copy image data into staging buffer"); | ||
|
||
if let Ok(mut image_data) = context.mut_device() | ||
.write_mapping(&image_upload_buffer, 0..upload_size) | ||
if let Ok(mut image_data) = device.write_mapping(&image_upload_buffer, 0..upload_size) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: move to the end of the previous line
}, | ||
]); | ||
device.update_descriptor_sets() | ||
.write(desc_data.sampled_image(&desc), 0, &[&image_srv as _]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can get rid of those X as _
things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately type inference does not seem to go through without it.
@@ -726,7 +726,7 @@ impl d::Device<B> for Device { | |||
color_attachments: &[&n::RenderTargetView], | |||
depth_stencil_attachments: &[&n::DepthStencilView], | |||
_extent: d::Extent, | |||
) -> Result<n::FrameBuffer, d::FramebufferError> { | |||
) -> Result<n::FrameBuffer, d::FrameBufferError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep it the old way. I believe saying Framebuffer
and Renderpass
consistently across core/backends would be nicer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are named FrameBuffer
and RenderPass
in the backend trait though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename the backend trait types then. I believe we did discuss this naming issue recently and agreed upon the Vulkan-like naming, right @msiglreith ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: we'll rename it outside of this PR. It's already big enough
@@ -96,6 +96,8 @@ pub struct DescriptorSetLayout; | |||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | |||
pub struct DescriptorSet; | |||
|
|||
#[allow(missing_copy_implementations)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this one to be the most annoying warning of all. I'd prefer to just put it as a top-level thing. In fact, it is already:
Line 4 in ad34a1e
#![allow(missing_docs, missing_copy_implementations)] |
@@ -512,7 +512,7 @@ impl core::Device<Backend> for Device { | |||
let base_ptr = buf.0.contents() as *mut u8; | |||
|
|||
if base_ptr.is_null() { | |||
return Err(mapping::Error::InvalidAccess); | |||
return Err(unimplemented!()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why unimplemented
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had removed core::mapping::Error::InvalidAccess
because it was originally for render, but it seems it came back with another meaning. Will put it back.
// TODO: view_image_as_depth_stencil | ||
/// | ||
#[allow(unused_variables)] | ||
fn view_image_as_depth_stencil(&mut self, image: &B::Image, format: format::Format, range: image::SubresourceRange) -> Result<B::DepthStencilView, TargetViewError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should use SubresourceLayers
let origin = image::Origin::User(memory); | ||
let stable_access = core::image::Access::empty(); | ||
let stable_layout = match usage { | ||
_ if usage.contains(COLOR_ATTACHMENT) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting matching
@Bastacyclop Here is one thing I think we should change w.r.t. typing. Currently, The way you use Instead, let's have |
|
@Bastacyclop ok, so it could be defined as pub trait MaybeTyped<B: Backend>: AsRef<handle::raw::Buffer<B>> {
type Data: Pod;
} |
Ok, the branch got accidentally pushed to |
Working on #1466.
I'm not familiar with the concepts yet so tell me if I'm missing something.