mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-21 19:32:49 +00:00
Merge #1103
1103: Fix Assorted Low-Hanging Validation and Error Message Issues r=kvark a=cwfitzgerald **Connections** Closes #1085 Closes #393 Closes #1053 **Description** These commits are independent and should be reviewed individually. Combined into a single PR to reduce noise. Overview of what was done: - Add validation for empty texture and buffer usage flags. (#393) - Add allowed texture usage flags to `format.describe()` (#1085) Validate new textures follow the allowed usage flags. - Properly validates vertex and buffers are bound. (#1053) Improves error messages when no vertex buffer is bound. (Before it said the limit was 0, now it says something is unbound) - Improve the vertex buffer overrun messages by keeping track of which slot has the smallest index. **Testing** Tested on examples by artificially creating the situation I am trying to validate, as well as running clean examples to make sure they pass validation. Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
commit
2287ae3f8a
@ -313,20 +313,22 @@ impl RenderBundleEncoder {
|
||||
first_instance,
|
||||
} => {
|
||||
let scope = PassErrorScope::Draw;
|
||||
let (vertex_limit, instance_limit) = state.vertex_limits();
|
||||
let vertex_limits = state.vertex_limits();
|
||||
let last_vertex = first_vertex + vertex_count;
|
||||
if last_vertex > vertex_limit {
|
||||
if last_vertex > vertex_limits.vertex_limit {
|
||||
return Err(DrawError::VertexBeyondLimit {
|
||||
last_vertex,
|
||||
vertex_limit,
|
||||
vertex_limit: vertex_limits.vertex_limit,
|
||||
slot: vertex_limits.vertex_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
let last_instance = first_instance + instance_count;
|
||||
if last_instance > instance_limit {
|
||||
if last_instance > vertex_limits.instance_limit {
|
||||
return Err(DrawError::InstanceBeyondLimit {
|
||||
last_instance,
|
||||
instance_limit,
|
||||
instance_limit: vertex_limits.instance_limit,
|
||||
slot: vertex_limits.instance_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
@ -343,7 +345,7 @@ impl RenderBundleEncoder {
|
||||
} => {
|
||||
let scope = PassErrorScope::DrawIndexed;
|
||||
//TODO: validate that base_vertex + max_index() is within the provided range
|
||||
let (_, instance_limit) = state.vertex_limits();
|
||||
let vertex_limits = state.vertex_limits();
|
||||
let index_limit = state.index.limit();
|
||||
let last_index = first_index + index_count;
|
||||
if last_index > index_limit {
|
||||
@ -354,10 +356,11 @@ impl RenderBundleEncoder {
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
let last_instance = first_instance + instance_count;
|
||||
if last_instance > instance_limit {
|
||||
if last_instance > vertex_limits.instance_limit {
|
||||
return Err(DrawError::InstanceBeyondLimit {
|
||||
last_instance,
|
||||
instance_limit,
|
||||
instance_limit: vertex_limits.instance_limit,
|
||||
slot: vertex_limits.instance_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
@ -855,6 +858,18 @@ impl PushConstantState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VertexLimitState {
|
||||
/// Length of the shortest vertex rate vertex buffer
|
||||
vertex_limit: u32,
|
||||
/// Buffer slot which the shortest vertex rate vertex buffer is bound to
|
||||
vertex_limit_slot: u32,
|
||||
/// Length of the shortest instance rate vertex buffer
|
||||
instance_limit: u32,
|
||||
/// Buffer slot which the shortest instance rate vertex buffer is bound to
|
||||
instance_limit_slot: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
trackers: TrackerSet,
|
||||
@ -869,20 +884,34 @@ struct State {
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn vertex_limits(&self) -> (u32, u32) {
|
||||
let mut vertex_limit = !0;
|
||||
let mut instance_limit = !0;
|
||||
for vbs in &self.vertex {
|
||||
fn vertex_limits(&self) -> VertexLimitState {
|
||||
let mut vert_state = VertexLimitState {
|
||||
vertex_limit: u32::MAX,
|
||||
vertex_limit_slot: 0,
|
||||
instance_limit: u32::MAX,
|
||||
instance_limit_slot: 0,
|
||||
};
|
||||
for (idx, vbs) in self.vertex.iter().enumerate() {
|
||||
if vbs.stride == 0 {
|
||||
continue;
|
||||
}
|
||||
let limit = ((vbs.range.end - vbs.range.start) / vbs.stride) as u32;
|
||||
match vbs.rate {
|
||||
wgt::InputStepMode::Vertex => vertex_limit = vertex_limit.min(limit),
|
||||
wgt::InputStepMode::Instance => instance_limit = instance_limit.min(limit),
|
||||
wgt::InputStepMode::Vertex => {
|
||||
if limit < vert_state.vertex_limit {
|
||||
vert_state.vertex_limit = limit;
|
||||
vert_state.vertex_limit_slot = idx as _;
|
||||
}
|
||||
}
|
||||
wgt::InputStepMode::Instance => {
|
||||
if limit < vert_state.instance_limit {
|
||||
vert_state.instance_limit = limit;
|
||||
vert_state.instance_limit_slot = idx as _;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(vertex_limit, instance_limit)
|
||||
vert_state
|
||||
}
|
||||
|
||||
fn invalidate_group_from(&mut self, slot: usize) {
|
||||
|
@ -26,23 +26,37 @@ pub enum DrawError {
|
||||
MissingBlendColor,
|
||||
#[error("render pipeline must be set")]
|
||||
MissingPipeline,
|
||||
#[error("vertex buffer {index} must be set")]
|
||||
MissingVertexBuffer { index: u32 },
|
||||
#[error("index buffer must be set")]
|
||||
MissingIndexBuffer,
|
||||
#[error("current render pipeline has a layout which is incompatible with a currently set bind group, first differing at entry index {index}")]
|
||||
IncompatibleBindGroup {
|
||||
index: u32,
|
||||
//expected: BindGroupLayoutId,
|
||||
//provided: Option<(BindGroupLayoutId, BindGroupId)>,
|
||||
},
|
||||
#[error("vertex {last_vertex} extends beyond limit {vertex_limit}")]
|
||||
VertexBeyondLimit { last_vertex: u32, vertex_limit: u32 },
|
||||
#[error("instance {last_instance} extends beyond limit {instance_limit}")]
|
||||
#[error("vertex {last_vertex} extends beyond limit {vertex_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Vertex` step-rate vertex buffer?")]
|
||||
VertexBeyondLimit {
|
||||
last_vertex: u32,
|
||||
vertex_limit: u32,
|
||||
slot: u32,
|
||||
},
|
||||
#[error("instance {last_instance} extends beyond limit {instance_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Instance` step-rate vertex buffer?")]
|
||||
InstanceBeyondLimit {
|
||||
last_instance: u32,
|
||||
instance_limit: u32,
|
||||
slot: u32,
|
||||
},
|
||||
#[error("index {last_index} extends beyond limit {index_limit}")]
|
||||
#[error("index {last_index} extends beyond limit {index_limit}. Did you bind the correct index buffer?")]
|
||||
IndexBeyondLimit { last_index: u32, index_limit: u32 },
|
||||
#[error("pipeline index format and buffer index format do not match")]
|
||||
UnmatchedIndexFormats,
|
||||
#[error(
|
||||
"pipeline index format ({pipeline:?}) and buffer index format ({buffer:?}) do not match"
|
||||
)]
|
||||
UnmatchedIndexFormats {
|
||||
pipeline: wgt::IndexFormat,
|
||||
buffer: wgt::IndexFormat,
|
||||
},
|
||||
}
|
||||
|
||||
/// Error encountered when encoding a render command.
|
||||
|
@ -226,7 +226,7 @@ impl OptionalState {
|
||||
#[derive(Debug, Default)]
|
||||
struct IndexState {
|
||||
bound_buffer_view: Option<(id::Valid<id::BufferId>, Range<BufferAddress>)>,
|
||||
format: IndexFormat,
|
||||
format: Option<IndexFormat>,
|
||||
pipeline_format: Option<IndexFormat>,
|
||||
limit: u32,
|
||||
}
|
||||
@ -235,7 +235,10 @@ impl IndexState {
|
||||
fn update_limit(&mut self) {
|
||||
self.limit = match self.bound_buffer_view {
|
||||
Some((_, ref range)) => {
|
||||
let shift = match self.format {
|
||||
let format = self
|
||||
.format
|
||||
.expect("IndexState::update_limit must be called after a index buffer is set");
|
||||
let shift = match format {
|
||||
IndexFormat::Uint16 => 1,
|
||||
IndexFormat::Uint32 => 2,
|
||||
};
|
||||
@ -256,6 +259,7 @@ struct VertexBufferState {
|
||||
total_size: BufferAddress,
|
||||
stride: BufferAddress,
|
||||
rate: InputStepMode,
|
||||
bound: bool,
|
||||
}
|
||||
|
||||
impl VertexBufferState {
|
||||
@ -263,28 +267,47 @@ impl VertexBufferState {
|
||||
total_size: 0,
|
||||
stride: 0,
|
||||
rate: InputStepMode::Vertex,
|
||||
bound: false,
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct VertexState {
|
||||
inputs: ArrayVec<[VertexBufferState; MAX_VERTEX_BUFFERS]>,
|
||||
/// Length of the shortest vertex rate vertex buffer
|
||||
vertex_limit: u32,
|
||||
/// Buffer slot which the shortest vertex rate vertex buffer is bound to
|
||||
vertex_limit_slot: u32,
|
||||
/// Length of the shortest instance rate vertex buffer
|
||||
instance_limit: u32,
|
||||
/// Buffer slot which the shortest instance rate vertex buffer is bound to
|
||||
instance_limit_slot: u32,
|
||||
/// Total amount of buffers required by the pipeline.
|
||||
buffers_required: u32,
|
||||
}
|
||||
|
||||
impl VertexState {
|
||||
fn update_limits(&mut self) {
|
||||
self.vertex_limit = !0;
|
||||
self.instance_limit = !0;
|
||||
for vbs in &self.inputs {
|
||||
if vbs.stride == 0 {
|
||||
self.vertex_limit = u32::MAX;
|
||||
self.instance_limit = u32::MAX;
|
||||
for (idx, vbs) in self.inputs.iter().enumerate() {
|
||||
if vbs.stride == 0 || !vbs.bound {
|
||||
continue;
|
||||
}
|
||||
let limit = (vbs.total_size / vbs.stride) as u32;
|
||||
match vbs.rate {
|
||||
InputStepMode::Vertex => self.vertex_limit = self.vertex_limit.min(limit),
|
||||
InputStepMode::Instance => self.instance_limit = self.instance_limit.min(limit),
|
||||
InputStepMode::Vertex => {
|
||||
if limit < self.vertex_limit {
|
||||
self.vertex_limit = limit;
|
||||
self.vertex_limit_slot = idx as _;
|
||||
}
|
||||
}
|
||||
InputStepMode::Instance => {
|
||||
if limit < self.instance_limit {
|
||||
self.instance_limit = limit;
|
||||
self.instance_limit_slot = idx as _;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,7 +333,15 @@ struct State {
|
||||
|
||||
impl State {
|
||||
fn is_ready(&self) -> Result<(), DrawError> {
|
||||
//TODO: vertex buffers
|
||||
// Determine how many vertex buffers have already been bound
|
||||
let bound_buffers = self.vertex.inputs.iter().take_while(|v| v.bound).count() as u32;
|
||||
// Compare with the needed quantity
|
||||
if bound_buffers < self.vertex.buffers_required {
|
||||
return Err(DrawError::MissingVertexBuffer {
|
||||
index: bound_buffers,
|
||||
});
|
||||
}
|
||||
|
||||
let bind_mask = self.binder.invalid_mask();
|
||||
if bind_mask != 0 {
|
||||
//let (expected, provided) = self.binder.entries[index as usize].info();
|
||||
@ -324,9 +355,17 @@ impl State {
|
||||
if self.blend_color == OptionalState::Required {
|
||||
return Err(DrawError::MissingBlendColor);
|
||||
}
|
||||
// Pipeline expects an index buffer
|
||||
if let Some(pipeline_index_format) = self.index.pipeline_format {
|
||||
if pipeline_index_format != self.index.format {
|
||||
return Err(DrawError::UnmatchedIndexFormats);
|
||||
// We have a buffer bound
|
||||
let buffer_index_format = self.index.format.ok_or(DrawError::MissingIndexBuffer)?;
|
||||
|
||||
// The buffers are different formats
|
||||
if pipeline_index_format != buffer_index_format {
|
||||
return Err(DrawError::UnmatchedIndexFormats {
|
||||
pipeline: pipeline_index_format,
|
||||
buffer: buffer_index_format,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -1188,9 +1227,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
state.index.pipeline_format = pipeline.index_format;
|
||||
|
||||
let vertex_strides_len = pipeline.vertex_strides.len();
|
||||
state.vertex.buffers_required = vertex_strides_len as u32;
|
||||
|
||||
while state.vertex.inputs.len() < vertex_strides_len {
|
||||
state.vertex.inputs.push(VertexBufferState::EMPTY);
|
||||
}
|
||||
|
||||
// Update vertex buffer limits
|
||||
for (vbs, &(stride, rate)) in
|
||||
state.vertex.inputs.iter_mut().zip(&pipeline.vertex_strides)
|
||||
@ -1229,14 +1271,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
};
|
||||
state.index.bound_buffer_view = Some((id::Valid(buffer_id), offset..end));
|
||||
|
||||
state.index.format = index_format;
|
||||
state.index.format = Some(index_format);
|
||||
state.index.update_limit();
|
||||
|
||||
let range = hal::buffer::SubRange {
|
||||
offset,
|
||||
size: Some(end - offset),
|
||||
};
|
||||
let index_type = conv::map_index_format(state.index.format);
|
||||
let index_type = conv::map_index_format(index_format);
|
||||
unsafe {
|
||||
raw.bind_index_buffer(buf_raw, range, index_type);
|
||||
}
|
||||
@ -1265,10 +1307,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.vertex
|
||||
.inputs
|
||||
.extend(iter::repeat(VertexBufferState::EMPTY).take(empty_slots));
|
||||
state.vertex.inputs[slot as usize].total_size = match size {
|
||||
let vertex_state = &mut state.vertex.inputs[slot as usize];
|
||||
vertex_state.total_size = match size {
|
||||
Some(s) => s.get(),
|
||||
None => buffer.size - offset,
|
||||
};
|
||||
vertex_state.bound = true;
|
||||
|
||||
let range = hal::buffer::SubRange {
|
||||
offset,
|
||||
@ -1400,6 +1444,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
return Err(DrawError::VertexBeyondLimit {
|
||||
last_vertex,
|
||||
vertex_limit,
|
||||
slot: state.vertex.vertex_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
@ -1409,6 +1454,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
return Err(DrawError::InstanceBeyondLimit {
|
||||
last_instance,
|
||||
instance_limit,
|
||||
slot: state.vertex.instance_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
@ -1446,6 +1492,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
return Err(DrawError::InstanceBeyondLimit {
|
||||
last_instance,
|
||||
instance_limit,
|
||||
slot: state.vertex.instance_limit_slot,
|
||||
})
|
||||
.map_pass_err(scope);
|
||||
}
|
||||
|
@ -438,6 +438,10 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
}
|
||||
|
||||
if desc.usage.is_empty() {
|
||||
return Err(resource::CreateBufferError::EmptyUsage);
|
||||
}
|
||||
|
||||
let mem_usage = {
|
||||
use gpu_alloc::UsageFlags as Uf;
|
||||
use wgt::BufferUsage as Bu;
|
||||
@ -516,7 +520,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
) -> Result<resource::Texture<B>, resource::CreateTextureError> {
|
||||
debug_assert_eq!(self_id.backend(), B::VARIANT);
|
||||
|
||||
let features = desc.format.describe().features;
|
||||
let format_desc = desc.format.describe();
|
||||
let features = format_desc.features;
|
||||
if !self.features.contains(features) {
|
||||
return Err(resource::CreateTextureError::MissingFeature(
|
||||
features,
|
||||
@ -537,6 +542,18 @@ impl<B: GfxBackend> Device<B> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if desc.usage.is_empty() {
|
||||
return Err(resource::CreateTextureError::EmptyUsage);
|
||||
}
|
||||
|
||||
let missing_features = desc.usage - format_desc.allowed_usages;
|
||||
if !missing_features.is_empty() {
|
||||
return Err(resource::CreateTextureError::InvalidUsages(
|
||||
missing_features,
|
||||
desc.format,
|
||||
));
|
||||
}
|
||||
|
||||
let kind = conv::map_texture_dimension_size(desc.dimension, desc.size, desc.sample_count)?;
|
||||
let format = conv::map_texture_format(desc.format, self.private_features);
|
||||
let aspects = format.surface_desc().aspects;
|
||||
|
@ -174,6 +174,8 @@ pub enum CreateBufferError {
|
||||
AccessError(#[from] BufferAccessError),
|
||||
#[error("buffers that are mapped at creation have to be aligned to `COPY_BUFFER_ALIGNMENT`")]
|
||||
UnalignedSize,
|
||||
#[error("Buffers cannot have empty usage flags")]
|
||||
EmptyUsage,
|
||||
#[error("`MAP` usage can only be combined with the opposite `COPY`, requested {0:?}")]
|
||||
UsageMismatch(wgt::BufferUsage),
|
||||
}
|
||||
@ -230,10 +232,14 @@ pub enum CreateTextureError {
|
||||
Device(#[from] DeviceError),
|
||||
#[error("D24Plus textures cannot be copied")]
|
||||
CannotCopyD24Plus,
|
||||
#[error("Textures cannot have empty usage flags")]
|
||||
EmptyUsage,
|
||||
#[error(transparent)]
|
||||
InvalidDimension(#[from] TextureDimensionError),
|
||||
#[error("texture descriptor mip level count ({0}) is invalid")]
|
||||
InvalidMipLevelCount(u32),
|
||||
#[error("The texture usages {0:?} are not allowed on a texture of type {1:?}")]
|
||||
InvalidUsages(wgt::TextureUsage, wgt::TextureFormat),
|
||||
#[error("Feature {0:?} must be enabled to create a texture of type {1:?}")]
|
||||
MissingFeature(wgt::Features, wgt::TextureFormat),
|
||||
}
|
||||
|
@ -766,6 +766,8 @@ pub struct TextureFormatInfo {
|
||||
pub block_size: u8,
|
||||
/// Format will have colors be converted from srgb to linear on read and from linear to srgb on write.
|
||||
pub srgb: bool,
|
||||
/// Allowed usage flags for the format.
|
||||
pub allowed_usages: TextureUsage,
|
||||
}
|
||||
|
||||
/// Underlying texture data format.
|
||||
@ -1158,135 +1160,141 @@ pub enum TextureFormat {
|
||||
impl TextureFormat {
|
||||
/// Get useful information about the texture format.
|
||||
pub fn describe(&self) -> TextureFormatInfo {
|
||||
#![allow(bindings_with_variant_name, non_snake_case)]
|
||||
|
||||
// Features
|
||||
let NATIVE = Features::empty();
|
||||
let BC = Features::TEXTURE_COMPRESSION_BC;
|
||||
let ETC2 = Features::TEXTURE_COMPRESSION_ETC2;
|
||||
let ASTC_LDR = Features::TEXTURE_COMPRESSION_ASTC_LDR;
|
||||
let native = Features::empty();
|
||||
let bc = Features::TEXTURE_COMPRESSION_BC;
|
||||
let etc2 = Features::TEXTURE_COMPRESSION_ETC2;
|
||||
let astc_ldr = Features::TEXTURE_COMPRESSION_ASTC_LDR;
|
||||
|
||||
// Sample Types
|
||||
let Uint = TextureSampleType::Uint;
|
||||
let Sint = TextureSampleType::Sint;
|
||||
let Nearest = TextureSampleType::Float { filterable: false };
|
||||
let Float = TextureSampleType::Float { filterable: true };
|
||||
let Depth = TextureSampleType::Depth;
|
||||
let uint = TextureSampleType::Uint;
|
||||
let sint = TextureSampleType::Sint;
|
||||
let nearest = TextureSampleType::Float { filterable: false };
|
||||
let float = TextureSampleType::Float { filterable: true };
|
||||
let depth = TextureSampleType::Depth;
|
||||
|
||||
// Color spaces
|
||||
let Linear = false;
|
||||
let Srgb = true;
|
||||
let linear = false;
|
||||
let srgb = true;
|
||||
|
||||
let (features, sample_type, srgb, block_dimensions, block_size) = match self {
|
||||
// Flags
|
||||
let basic = TextureUsage::COPY_SRC | TextureUsage::COPY_DST | TextureUsage::SAMPLED;
|
||||
let attachment = basic | TextureUsage::RENDER_ATTACHMENT;
|
||||
let storage = basic | TextureUsage::STORAGE;
|
||||
let all_flags = TextureUsage::all();
|
||||
|
||||
// See https://gpuweb.github.io/gpuweb/#texture-format-caps for reference
|
||||
let (features, sample_type, srgb, block_dimensions, block_size, allowed_usages) = match self
|
||||
{
|
||||
// Normal 8 bit textures
|
||||
Self::R8Unorm => (NATIVE, Float, Linear, (1, 1), 1),
|
||||
Self::R8Snorm => (NATIVE, Float, Linear, (1, 1), 1),
|
||||
Self::R8Uint => (NATIVE, Uint, Linear, (1, 1), 1),
|
||||
Self::R8Sint => (NATIVE, Sint, Linear, (1, 1), 1),
|
||||
Self::R8Unorm => (native, float, linear, (1, 1), 1, attachment),
|
||||
Self::R8Snorm => (native, float, linear, (1, 1), 1, basic),
|
||||
Self::R8Uint => (native, uint, linear, (1, 1), 1, attachment),
|
||||
Self::R8Sint => (native, sint, linear, (1, 1), 1, attachment),
|
||||
|
||||
// Normal 16 bit textures
|
||||
Self::R16Uint => (NATIVE, Uint, Linear, (1, 1), 2),
|
||||
Self::R16Sint => (NATIVE, Sint, Linear, (1, 1), 2),
|
||||
Self::R16Float => (NATIVE, Float, Linear, (1, 1), 2),
|
||||
Self::Rg8Unorm => (NATIVE, Float, Linear, (1, 1), 2),
|
||||
Self::Rg8Snorm => (NATIVE, Float, Linear, (1, 1), 2),
|
||||
Self::Rg8Uint => (NATIVE, Uint, Linear, (1, 1), 2),
|
||||
Self::Rg8Sint => (NATIVE, Sint, Linear, (1, 1), 2),
|
||||
Self::R16Uint => (native, uint, linear, (1, 1), 2, attachment),
|
||||
Self::R16Sint => (native, sint, linear, (1, 1), 2, attachment),
|
||||
Self::R16Float => (native, float, linear, (1, 1), 2, attachment),
|
||||
Self::Rg8Unorm => (native, float, linear, (1, 1), 2, attachment),
|
||||
Self::Rg8Snorm => (native, float, linear, (1, 1), 2, attachment),
|
||||
Self::Rg8Uint => (native, uint, linear, (1, 1), 2, attachment),
|
||||
Self::Rg8Sint => (native, sint, linear, (1, 1), 2, basic),
|
||||
|
||||
// Normal 32 bit textures
|
||||
Self::R32Uint => (NATIVE, Uint, Linear, (1, 1), 4),
|
||||
Self::R32Sint => (NATIVE, Sint, Linear, (1, 1), 4),
|
||||
Self::R32Float => (NATIVE, Nearest, Linear, (1, 1), 4),
|
||||
Self::Rg16Uint => (NATIVE, Uint, Linear, (1, 1), 4),
|
||||
Self::Rg16Sint => (NATIVE, Sint, Linear, (1, 1), 4),
|
||||
Self::Rg16Float => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Rgba8Unorm => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Rgba8UnormSrgb => (NATIVE, Float, Srgb, (1, 1), 4),
|
||||
Self::Rgba8Snorm => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Rgba8Uint => (NATIVE, Uint, Linear, (1, 1), 4),
|
||||
Self::Rgba8Sint => (NATIVE, Sint, Linear, (1, 1), 4),
|
||||
Self::Bgra8Unorm => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Bgra8UnormSrgb => (NATIVE, Float, Srgb, (1, 1), 4),
|
||||
Self::R32Uint => (native, uint, linear, (1, 1), 4, all_flags),
|
||||
Self::R32Sint => (native, sint, linear, (1, 1), 4, all_flags),
|
||||
Self::R32Float => (native, nearest, linear, (1, 1), 4, all_flags),
|
||||
Self::Rg16Uint => (native, uint, linear, (1, 1), 4, attachment),
|
||||
Self::Rg16Sint => (native, sint, linear, (1, 1), 4, attachment),
|
||||
Self::Rg16Float => (native, float, linear, (1, 1), 4, attachment),
|
||||
Self::Rgba8Unorm => (native, float, linear, (1, 1), 4, all_flags),
|
||||
Self::Rgba8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment),
|
||||
Self::Rgba8Snorm => (native, float, linear, (1, 1), 4, storage),
|
||||
Self::Rgba8Uint => (native, uint, linear, (1, 1), 4, all_flags),
|
||||
Self::Rgba8Sint => (native, sint, linear, (1, 1), 4, all_flags),
|
||||
Self::Bgra8Unorm => (native, float, linear, (1, 1), 4, attachment),
|
||||
Self::Bgra8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment),
|
||||
|
||||
// Packed 32 bit textures
|
||||
Self::Rgb10a2Unorm => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Rg11b10Float => (NATIVE, Float, Linear, (1, 1), 4),
|
||||
Self::Rgb10a2Unorm => (native, float, linear, (1, 1), 4, attachment),
|
||||
Self::Rg11b10Float => (native, float, linear, (1, 1), 4, basic),
|
||||
|
||||
// Packed 32 bit textures
|
||||
Self::Rg32Uint => (NATIVE, Uint, Linear, (1, 1), 8),
|
||||
Self::Rg32Sint => (NATIVE, Sint, Linear, (1, 1), 8),
|
||||
Self::Rg32Float => (NATIVE, Nearest, Linear, (1, 1), 8),
|
||||
Self::Rgba16Uint => (NATIVE, Uint, Linear, (1, 1), 8),
|
||||
Self::Rgba16Sint => (NATIVE, Sint, Linear, (1, 1), 8),
|
||||
Self::Rgba16Float => (NATIVE, Float, Linear, (1, 1), 8),
|
||||
Self::Rg32Uint => (native, uint, linear, (1, 1), 8, all_flags),
|
||||
Self::Rg32Sint => (native, sint, linear, (1, 1), 8, all_flags),
|
||||
Self::Rg32Float => (native, nearest, linear, (1, 1), 8, all_flags),
|
||||
Self::Rgba16Uint => (native, uint, linear, (1, 1), 8, all_flags),
|
||||
Self::Rgba16Sint => (native, sint, linear, (1, 1), 8, all_flags),
|
||||
Self::Rgba16Float => (native, float, linear, (1, 1), 8, all_flags),
|
||||
|
||||
// Packed 32 bit textures
|
||||
Self::Rgba32Uint => (NATIVE, Uint, Linear, (1, 1), 16),
|
||||
Self::Rgba32Sint => (NATIVE, Sint, Linear, (1, 1), 16),
|
||||
Self::Rgba32Float => (NATIVE, Nearest, Linear, (1, 1), 16),
|
||||
Self::Rgba32Uint => (native, uint, linear, (1, 1), 16, all_flags),
|
||||
Self::Rgba32Sint => (native, sint, linear, (1, 1), 16, all_flags),
|
||||
Self::Rgba32Float => (native, nearest, linear, (1, 1), 16, all_flags),
|
||||
|
||||
// Depth-stencil textures
|
||||
Self::Depth32Float => (NATIVE, Depth, Linear, (1, 1), 4),
|
||||
Self::Depth24Plus => (NATIVE, Depth, Linear, (1, 1), 4),
|
||||
Self::Depth24PlusStencil8 => (NATIVE, Depth, Linear, (1, 1), 4),
|
||||
Self::Depth32Float => (native, depth, linear, (1, 1), 4, attachment),
|
||||
Self::Depth24Plus => (native, depth, linear, (1, 1), 4, attachment),
|
||||
Self::Depth24PlusStencil8 => (native, depth, linear, (1, 1), 4, attachment),
|
||||
|
||||
// BCn compressed textures
|
||||
Self::Bc1RgbaUnorm => (BC, Float, Linear, (4, 4), 8),
|
||||
Self::Bc1RgbaUnormSrgb => (BC, Float, Srgb, (4, 4), 8),
|
||||
Self::Bc2RgbaUnorm => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc2RgbaUnormSrgb => (BC, Float, Srgb, (4, 4), 16),
|
||||
Self::Bc3RgbaUnorm => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc3RgbaUnormSrgb => (BC, Float, Srgb, (4, 4), 16),
|
||||
Self::Bc4RUnorm => (BC, Float, Linear, (4, 4), 8),
|
||||
Self::Bc4RSnorm => (BC, Float, Linear, (4, 4), 8),
|
||||
Self::Bc5RgUnorm => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc5RgSnorm => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc6hRgbUfloat => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc6hRgbSfloat => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc7RgbaUnorm => (BC, Float, Linear, (4, 4), 16),
|
||||
Self::Bc7RgbaUnormSrgb => (BC, Float, Srgb, (4, 4), 16),
|
||||
Self::Bc1RgbaUnorm => (bc, float, linear, (4, 4), 8, basic),
|
||||
Self::Bc1RgbaUnormSrgb => (bc, float, srgb, (4, 4), 8, basic),
|
||||
Self::Bc2RgbaUnorm => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc2RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic),
|
||||
Self::Bc3RgbaUnorm => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc3RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic),
|
||||
Self::Bc4RUnorm => (bc, float, linear, (4, 4), 8, basic),
|
||||
Self::Bc4RSnorm => (bc, float, linear, (4, 4), 8, basic),
|
||||
Self::Bc5RgUnorm => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc5RgSnorm => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc6hRgbUfloat => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc6hRgbSfloat => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc7RgbaUnorm => (bc, float, linear, (4, 4), 16, basic),
|
||||
Self::Bc7RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic),
|
||||
|
||||
// ETC compressed textures
|
||||
Self::Etc2RgbUnorm => (ETC2, Float, Linear, (4, 4), 8),
|
||||
Self::Etc2RgbUnormSrgb => (ETC2, Float, Srgb, (4, 4), 8),
|
||||
Self::Etc2RgbA1Unorm => (ETC2, Float, Linear, (4, 4), 8),
|
||||
Self::Etc2RgbA1UnormSrgb => (ETC2, Float, Srgb, (4, 4), 8),
|
||||
Self::Etc2RgbA8Unorm => (ETC2, Float, Linear, (4, 4), 16),
|
||||
Self::Etc2RgbA8UnormSrgb => (ETC2, Float, Srgb, (4, 4), 16),
|
||||
Self::EacRUnorm => (ETC2, Float, Linear, (4, 4), 8),
|
||||
Self::EacRSnorm => (ETC2, Float, Linear, (4, 4), 8),
|
||||
Self::EtcRgUnorm => (ETC2, Float, Linear, (4, 4), 16),
|
||||
Self::EtcRgSnorm => (ETC2, Float, Linear, (4, 4), 16),
|
||||
Self::Etc2RgbUnorm => (etc2, float, linear, (4, 4), 8, basic),
|
||||
Self::Etc2RgbUnormSrgb => (etc2, float, srgb, (4, 4), 8, basic),
|
||||
Self::Etc2RgbA1Unorm => (etc2, float, linear, (4, 4), 8, basic),
|
||||
Self::Etc2RgbA1UnormSrgb => (etc2, float, srgb, (4, 4), 8, basic),
|
||||
Self::Etc2RgbA8Unorm => (etc2, float, linear, (4, 4), 16, basic),
|
||||
Self::Etc2RgbA8UnormSrgb => (etc2, float, srgb, (4, 4), 16, basic),
|
||||
Self::EacRUnorm => (etc2, float, linear, (4, 4), 8, basic),
|
||||
Self::EacRSnorm => (etc2, float, linear, (4, 4), 8, basic),
|
||||
Self::EtcRgUnorm => (etc2, float, linear, (4, 4), 16, basic),
|
||||
Self::EtcRgSnorm => (etc2, float, linear, (4, 4), 16, basic),
|
||||
|
||||
// ASTC compressed textures
|
||||
Self::Astc4x4RgbaUnorm => (ASTC_LDR, Float, Linear, (4, 4), 16),
|
||||
Self::Astc4x4RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (4, 4), 16),
|
||||
Self::Astc5x4RgbaUnorm => (ASTC_LDR, Float, Linear, (5, 4), 16),
|
||||
Self::Astc5x4RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (5, 4), 16),
|
||||
Self::Astc5x5RgbaUnorm => (ASTC_LDR, Float, Linear, (5, 5), 16),
|
||||
Self::Astc5x5RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (5, 5), 16),
|
||||
Self::Astc6x5RgbaUnorm => (ASTC_LDR, Float, Linear, (6, 5), 16),
|
||||
Self::Astc6x5RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (6, 5), 16),
|
||||
Self::Astc6x6RgbaUnorm => (ASTC_LDR, Float, Linear, (6, 6), 16),
|
||||
Self::Astc6x6RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (6, 6), 16),
|
||||
Self::Astc8x5RgbaUnorm => (ASTC_LDR, Float, Linear, (8, 5), 16),
|
||||
Self::Astc8x5RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (8, 5), 16),
|
||||
Self::Astc8x6RgbaUnorm => (ASTC_LDR, Float, Linear, (8, 6), 16),
|
||||
Self::Astc8x6RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (8, 6), 16),
|
||||
Self::Astc10x5RgbaUnorm => (ASTC_LDR, Float, Linear, (10, 5), 16),
|
||||
Self::Astc10x5RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (10, 5), 16),
|
||||
Self::Astc10x6RgbaUnorm => (ASTC_LDR, Float, Linear, (10, 6), 16),
|
||||
Self::Astc10x6RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (10, 6), 16),
|
||||
Self::Astc8x8RgbaUnorm => (ASTC_LDR, Float, Linear, (8, 8), 16),
|
||||
Self::Astc8x8RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (8, 8), 16),
|
||||
Self::Astc10x8RgbaUnorm => (ASTC_LDR, Float, Linear, (10, 8), 16),
|
||||
Self::Astc10x8RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (10, 8), 16),
|
||||
Self::Astc10x10RgbaUnorm => (ASTC_LDR, Float, Linear, (10, 10), 16),
|
||||
Self::Astc10x10RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (10, 10), 16),
|
||||
Self::Astc12x10RgbaUnorm => (ASTC_LDR, Float, Linear, (12, 10), 16),
|
||||
Self::Astc12x10RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (12, 10), 16),
|
||||
Self::Astc12x12RgbaUnorm => (ASTC_LDR, Float, Linear, (12, 12), 16),
|
||||
Self::Astc12x12RgbaUnormSrgb => (ASTC_LDR, Float, Srgb, (12, 12), 16),
|
||||
Self::Astc4x4RgbaUnorm => (astc_ldr, float, linear, (4, 4), 16, basic),
|
||||
Self::Astc4x4RgbaUnormSrgb => (astc_ldr, float, srgb, (4, 4), 16, basic),
|
||||
Self::Astc5x4RgbaUnorm => (astc_ldr, float, linear, (5, 4), 16, basic),
|
||||
Self::Astc5x4RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 4), 16, basic),
|
||||
Self::Astc5x5RgbaUnorm => (astc_ldr, float, linear, (5, 5), 16, basic),
|
||||
Self::Astc5x5RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 5), 16, basic),
|
||||
Self::Astc6x5RgbaUnorm => (astc_ldr, float, linear, (6, 5), 16, basic),
|
||||
Self::Astc6x5RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 5), 16, basic),
|
||||
Self::Astc6x6RgbaUnorm => (astc_ldr, float, linear, (6, 6), 16, basic),
|
||||
Self::Astc6x6RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 6), 16, basic),
|
||||
Self::Astc8x5RgbaUnorm => (astc_ldr, float, linear, (8, 5), 16, basic),
|
||||
Self::Astc8x5RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 5), 16, basic),
|
||||
Self::Astc8x6RgbaUnorm => (astc_ldr, float, linear, (8, 6), 16, basic),
|
||||
Self::Astc8x6RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 6), 16, basic),
|
||||
Self::Astc10x5RgbaUnorm => (astc_ldr, float, linear, (10, 5), 16, basic),
|
||||
Self::Astc10x5RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 5), 16, basic),
|
||||
Self::Astc10x6RgbaUnorm => (astc_ldr, float, linear, (10, 6), 16, basic),
|
||||
Self::Astc10x6RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 6), 16, basic),
|
||||
Self::Astc8x8RgbaUnorm => (astc_ldr, float, linear, (8, 8), 16, basic),
|
||||
Self::Astc8x8RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 8), 16, basic),
|
||||
Self::Astc10x8RgbaUnorm => (astc_ldr, float, linear, (10, 8), 16, basic),
|
||||
Self::Astc10x8RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 8), 16, basic),
|
||||
Self::Astc10x10RgbaUnorm => (astc_ldr, float, linear, (10, 10), 16, basic),
|
||||
Self::Astc10x10RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 10), 16, basic),
|
||||
Self::Astc12x10RgbaUnorm => (astc_ldr, float, linear, (12, 10), 16, basic),
|
||||
Self::Astc12x10RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 10), 16, basic),
|
||||
Self::Astc12x12RgbaUnorm => (astc_ldr, float, linear, (12, 12), 16, basic),
|
||||
Self::Astc12x12RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 12), 16, basic),
|
||||
};
|
||||
|
||||
TextureFormatInfo {
|
||||
@ -1295,6 +1303,7 @@ impl TextureFormat {
|
||||
block_dimensions,
|
||||
block_size,
|
||||
srgb,
|
||||
allowed_usages,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user