Wgpu-rs: skybox cubemap example

Created on 8 Oct 2019  路  28Comments  路  Source: gfx-rs/wgpu-rs

A new example for how to write an idiomatic skybox with a cubemap in wgpu-rs would be great.

Opening this issue in case there鈥檚 some superhuman out there who wants to help us all out

enhancement help wanted

Most helpful comment

I'll take a stab at this and hopefully submit a PR soon.

All 28 comments

Here鈥檚 an older GL reference which explains the general idea of a skybox in case someone doesn鈥檛 know what it is, or how it works: http://ogldev.atspace.co.uk/www/tutorial25/tutorial25.html

I'll take a stab at this and hopefully submit a PR soon.

ping @caelunshun any progress on this?

ping @caelunshun any progress on this?

I've been a bit busy lately, but I still plan to complete this. Should be done sometime this week.

So I started messing around with what a skybox might look like, and i think i'm stuck trying to figure out how to get TextureDimensions, TextureViewDimensions, the backing texture, and texture views working right; i think you'd have to do something like:

let render_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
    bindings: &[
        wgpu::BindGroupLayoutBinding {
            binding: 0,
            visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
            ty: wgpu::BindingType::UniformBuffer { dynamic: false },
        },
        wgpu::BindGroupLayoutBinding {
            binding: 2,
            visibility: wgpu::ShaderStage::FRAGMENT,
            ty: wgpu::BindingType::SampledTexture {
                multisampled: false,
                dimension: wgpu::TextureViewDimension::Cube,
            },
        },
    ],
});

...

// FIXME: what do we do here?
let texture_extent = wgpu::Extent3d {
    width: 100,
    height: 100,
    // width: image_width,
    // height: image_height,
    depth: 1, // do we use the extend to index into 1 of the 6 faces of the cubemap?
};

let texture = device.create_texture(&wgpu::TextureDescriptor {
    size: texture_extent,
    array_layer_count: 1,
    mip_level_count: 1,
    sample_count: 1,
    dimension: wgpu::TextureDimension::D3, // is this a d2 or a d3...?
    format: SKYBOX_FORMAT,
    usage: wgpu::TextureUsage::SAMPLED
        | wgpu::TextureUsage::COPY_DST
        | wgpu::TextureUsage::COPY_SRC,
});

{
    let mut encoder =
    device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });

    for (i, image) in faces.iter().enumerate() {
    let (image_width, image_height) = image.dimensions();
    let image_buf = device
        .create_buffer_mapped(
        image.len(),
        wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::COPY_DST,
        )
        .fill_from_slice(&image);
    encoder.copy_buffer_to_texture(
        wgpu::BufferCopyView {
        buffer: &image_buf,
        offset: 0,
        row_pitch: 4 * image_width,
        image_height,
        },
        wgpu::TextureCopyView {
        texture: &texture,
        mip_level: 0,
        array_layer: 0, // FIXME: or do we use this array layer as an offset?
        // FIXME: do we use this as an offset into the large cube texture?
        origin: wgpu::Origin3d {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        },
        },
        texture_extent,
    );
    }
}
...

let texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
    format: SKYBOX_FORMAT,
    dimension: wgpu::TextureViewDimension::Cube, // I assume we have to use Cube here and not D3?
    aspect: wgpu::TextureAspect::default(),
    base_mip_level: 1,
    level_count: 1,
    base_array_layer: 1,
    array_layer_count: 1,
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
    layout,
    bindings: &[
        wgpu::Binding {
            binding: 0,
            resource: wgpu::BindingResource::Buffer {
                buffer: &data.buf,
                range: 0..data.uniform_buf_size,
            },
        },
        wgpu::Binding {
            binding: 2,
            resource: wgpu::BindingResource::TextureView(&texture_view),
        },
    ],
});

But doing something like that gets one:

on an `Err` value: BadKind(Cube)'
...
  12: wgpu_native::device::texture_create_view
             at /home/m4b/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-native-0.3.3/src/device.rs:847
  13: wgpu_texture_create_view
             at /home/m4b/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-native-0.3.3/src/device.rs:938
  14: wgpu::Texture::create_view
             at /home/m4b/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.3.0/src/lib.rs:1026

Any hints @kvark (or whoever else might know) :) ?

Texture dimension should be D2 and the array layer count should be a multiple of 6. The texture view would also need to specify the array layer count (the same), but using Cube there is correct.

Hmm, when i change the array layer to 6, etc., I still get BadKind(Cube); looks like is_cube is false from the ImageCreation flags , e.g. is_cube is false here, image.flags is 0x0:

        let is_cube = image
            .flags
            .intersects(vk::ImageCreateFlags::CUBE_COMPATIBLE);
        let info = vk::ImageViewCreateInfo {
            s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::ImageViewCreateFlags::empty(),
            image: image.raw,
            view_type: match conv::map_view_kind(kind, image.ty, is_cube) {
                Some(ty) => ty,
                None => return Err(image::ViewError::BadKind(kind)),
            },

I don't know where the exact place influences those flags, is it in the usage during texture creation?

            usage: wgpu::TextureUsage::SAMPLED
                | wgpu::TextureUsage::COPY_DST
                | wgpu::TextureUsage::COPY_SRC,

Unfortunately I don't see a CUBE usage

I'm seeing a todo in device::create_texture, could this be the issue?

pub fn device_create_texture(
    device_id: DeviceId,
    desc: &resource::TextureDescriptor,
) -> resource::Texture<back::Backend> {
    let kind = conv::map_texture_dimension_size(desc.dimension, desc.size, desc.array_layer_count, desc.sample_count);
    let format = conv::map_texture_format(desc.format);
    let aspects = format.surface_desc().aspects;
    let usage = conv::map_texture_usage(desc.usage, aspects);

    let (device_guard, _) = HUB.devices.read(&mut Token::root());
    let device = &device_guard[device_id];

    assert!((desc.mip_level_count as usize) < MAX_MIP_LEVELS);

    let mut image = unsafe {
        device.raw.create_image(
            kind,
            desc.mip_level_count as hal::image::Level,
            format,
            hal::image::Tiling::Optimal,
            usage,
            hal::image::ViewCapabilities::empty(), // TODO: format, 2d array, cube
        )
    }
    .unwrap();

Yup, in the vulkan backend, looks like flags is derived from ViewCapabilities:

    unsafe fn create_image(
        &self,
        kind: image::Kind,
        mip_levels: image::Level,
        format: format::Format,
        tiling: image::Tiling,
        usage: image::Usage,
        view_caps: image::ViewCapabilities,
    ) -> Result<n::Image, image::CreationError> {
        let flags = conv::map_view_capabilities(view_caps);

so pretty sure this is a wgpu-native issue :)

Yes, you are correct. The changes I requested are also correct - this is how it's supposed to work.
When this code was implemented in wgpu-native, I wasn't sure if the API will have an explicit CUBE_COMPATIBLE kind of flag. Now it's known that we have to imply that automatically for any 2D texture with the number of array layers being a multiple of 6 ... That's a fairly simple fix we need in wgpu-native before the skybox is available.

Yup, makes sense; can we try to sneak this in before wgpu 0.4?

@m4b it should be a fairly straightforward fix. Want to give it a shot?

yes i will look into it

lol looks like this is done already in master :]

        // 2D textures with array layer counts that are multiples of 6 could be cubemaps
        // Following gpuweb/gpuweb#68 always add the hint in that case
        if desc.dimension == TextureDimension::D2 && desc.array_layer_count % 6 == 0 {
            view_capabilities |= hal::image::ViewCapabilities::KIND_CUBE;
        };

        // TODO: 2D arrays, cubemap arrays

        let mut image = unsafe {
            self.raw.create_image(
                kind,
                desc.mip_level_count as hal::image::Level,
                format,
                hal::image::Tiling::Optimal,
                usage,
                view_capabilities,
            )
        }
        .unwrap();

let me test it out

current status: attempting to test led me to https://github.com/gfx-rs/wgpu/issues/364

Please try again, the master of wgpu-rs should have this issue fixed.

So after some fun, I've got wgpu master working, and a very rough skybox setup, but pretty sure it's not working because my copy stage is busted.

Split it up into different sections, the shaders, the setup, the validation errors, the image copy, and the bind group and draw call.

Shaders

looking at examples, I think the shaders would look something like this?

Only part that wasn't straightforward was the inverted proj matrix (i don't have that in my uniforms), but i think it's safe to invert in the shader a proj matrix we get?

Also was wondering if this was just the inverse projection matrix, or the inverse of the projection * view. Anyway:

skybox_vert.glsl:

#version 450
layout(location = 0) in vec2 position;

layout(location = 0) out vec3 v_uv;

layout(set = 0, binding = 0) uniform Data {
  mat4 view;
  mat4 proj;
};

void main() {
    mat3 invModelView = transpose(mat3(view));
    vec3 unProjected = (inverse(proj) * vec4(position, 0.0, 1.0)).xyz;
    v_uv = invModelView * unProjected;

    gl_Position = vec4(position, 0.0, 1.0);
}

skybox_frag.glsl:

#version 450

layout(set = 0, binding = 2) uniform samplerCube t_cubemap;

layout(location = 0) in vec3 v_uv;
layout(location = 0) out vec4 f_color;

void main() {
    f_color = vec4(texture(t_cubemap, v_uv));
}

Errors

shaders should compile without error; however, when using the rough version below, i get a _lot_ of validation errors.

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [UNASSIGNED-CoreValidation-Shader-DescriptorTypeMismatch (0)] : Type mismatch on descriptor slot 0.2 (expected `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`) but descriptor of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
object info: (type: UNKNOWN, hndl: 0)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 0 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 1 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 2 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 3 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 4 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR skybox] Copying skybox image 5 of size 200,200 to gpu
[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01486 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01486)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageMemoryBarrier-subresourceRange-01724 (0)] : vkCmdPipelineBarrier(): pImageMemoryBarriers[0].subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-subresourceRange-01724)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00197 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.x (0) and (imageExtent.width + imageOffset.x) (200) must be >= zero or <= image subresource width (0). The Vulkan spec states: imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00197)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00198 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.y (0) and (imageExtent.height + imageOffset.y) (200) must be >= zero or <= image subresource height (0). The Vulkan spec states: imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00198)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkBufferImageCopy-imageOffset-00200 (0)] : vkCmdCopyBufferToImage(): Both pRegion[0] imageoffset.z (0) and (imageExtent.depth + imageOffset.z) (1) must be >= zero or <= image subresource depth (0). The Vulkan spec states: imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkBufferImageCopy-imageOffset-00200)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-pRegions-00172 (0)] : vkCmdCopyBufferToImage(): pRegion[0] exceeds image bounds.. The Vulkan spec states: The image region specified by each element of pRegions must be a region that is contained within dstImage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00172)
object info: (type: COMMAND_BUFFER, hndl: 0)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-vkCmdCopyBufferToImage-imageSubresource-01701 (0)] : In vkCmdCopyBufferToImage(), pRegions[0].imageSubresource.mipLevel is 1, but provided VkImage 0x53[] has 1 mip levels. The Vulkan spec states: The imageSubresource.mipLevel member of each element of pRegions must be less than the mipLevels specified in VkImageCreateInfo when dstImage was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-imageSubresource-01701)
object info: (type: COMMAND_BUFFER, hndl: 94232413765760)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageViewCreateInfo-subresourceRange-01478 (0)] : vkCreateImageView: pCreateInfo->subresourceRange.baseMipLevel (= 1) is greater or equal to the mip level count of the image (i.e. greater or equal to 1). The Vulkan spec states: subresourceRange.baseMipLevel must be less than the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageViewCreateInfo-subresourceRange-01478)
object info: (type: IMAGE, hndl: 83)

[2019-10-31T04:01:16Z ERROR gfx_backend_vulkan] 
VALIDATION [VUID-VkImageViewCreateInfo-subresourceRange-01718 (0)] : vkCreateImageView: pCreateInfo->subresourceRange.baseMipLevel + .levelCount (= 1 + 1 = 2) is greater than the mip level count of the image (i.e. greater than 1). The Vulkan spec states: If subresourceRange.levelCount is not VK_REMAINING_MIP_LEVELS, subresourceRange.baseMipLevel + subresourceRange.levelCount must be less than or equal to the mipLevels specified in VkImageCreateInfo when image was created (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImageViewCreateInfo-subresourceRange-01718)
object info: (type: IMAGE, hndl: 83)

Very rough skybox setup

first stage, create render pipeline, creatte layouts, etc.

fn init(device: &mut wgpu::Device) {
let render_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
    bindings: &[
        wgpu::BindGroupLayoutBinding {
            binding: 0,
            visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
            ty: wgpu::BindingType::UniformBuffer { dynamic: false },
        },
        wgpu::BindGroupLayoutBinding {
            binding: 2,
            visibility: wgpu::ShaderStage::FRAGMENT,
            ty: wgpu::BindingType::SampledTexture {
                multisampled: false,
                dimension: wgpu::TextureViewDimension::Cube,
            },
        },
    ],
});

let vs_module = {
    let vs_bytes = loader.load("skybox_vert.spv")?;
    device.create_shader_module(vs_bytes)
};
let fs_module = {
    let fs_bytes = loader.load("skybox_frag.spv")?;
    device.create_shader_module(fs_bytes)
};

let attributes = [
    wgpu::VertexAttributeDescriptor {
        format: wgpu::VertexFormat::Float2,
        offset: 0,
        shader_location: 0,
    },
];

let stride = std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress;
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
    bind_group_layouts: &[&render_layout],
});

// Create the render pipeline
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
    layout: &pipeline_layout,
    vertex_stage: wgpu::ProgrammableStageDescriptor {
        module: &vs_module,
        entry_point: "main",
    },
    fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
        module: &fs_module,
        entry_point: "main",
    }),
    rasterization_state: Some(wgpu::RasterizationStateDescriptor {
        front_face: wgpu::FrontFace::Cw,
        cull_mode: wgpu::CullMode::Back,
        depth_bias: 0,
        depth_bias_slope_scale: 0.0,
        depth_bias_clamp: 0.0,
    }),
    primitive_topology: wgpu::PrimitiveTopology::TriangleList,
    color_states: &[wgpu::ColorStateDescriptor {
        format: sc_desc.format,
        color_blend: wgpu::BlendDescriptor::REPLACE,
        alpha_blend: wgpu::BlendDescriptor::REPLACE,
        write_mask: wgpu::ColorWrite::ALL,
    }],
    depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
        format: DEPTH_FORMAT,
        depth_write_enabled: true,
        depth_compare: wgpu::CompareFunction::Less,
        stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
        stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
        stencil_read_mask: 0,
        stencil_write_mask: 0,
    }),
    index_format: wgpu::IndexFormat::Uint16,
    vertex_buffers: &[wgpu::VertexBufferDescriptor {
        stride,
        step_mode: wgpu::InputStepMode::Vertex,
        attributes: &attributes,
    }],
    sample_count: 1,
    sample_mask: !0,
    alpha_to_coverage_enabled: false,
});

copy image data into texture, this part is what needs fixing i believe

fn copy(device: &mut wgpu::Device,
        faces: &[image::ImageBuffer<image::Rgba<u8>, Vec<u8>>]) {

let (image_width, image_height) = faces[0].dimensions();
let texture_extent = wgpu::Extent3d {
    width: image_width,
    height: image_height,
    depth: 1,
};
let texture = device.create_texture(&wgpu::TextureDescriptor {
    size: texture_extent,
    array_layer_count: 6,
    mip_level_count: 1,
    sample_count: 1,
    dimension: wgpu::TextureDimension::D2,
    format: SKYBOX_FORMAT,
    usage: wgpu::TextureUsage::SAMPLED
        | wgpu::TextureUsage::COPY_DST
        | wgpu::TextureUsage::COPY_SRC,
});

{
    let mut encoder =
        device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });

    for (i, image) in faces.iter().enumerate() {
        let (image_width, image_height) = image.dimensions();
        let image_buf = device
            .create_buffer_mapped(
                image.len(),
                wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::COPY_DST,
            )
            .fill_from_slice(&image);
        encoder.copy_buffer_to_texture(
            wgpu::BufferCopyView {
                buffer: &image_buf,
                offset: 0,
                row_pitch: 4 * image_width,
                image_height,
            },
            wgpu::TextureCopyView {
                texture: &texture,
                mip_level: 1, // setting this to 0 gets rid of some validation errors
                array_layer: i as u32,
                origin: wgpu::Origin3d {
                    x: 0.0,
                    y: 0.0,
                    z: 0.0,
                },
            },
            texture_extent,
        );
    }
}

bind group and draw

// bind group and draw
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
    format: SKYBOX_FORMAT,
    dimension: wgpu::TextureViewDimension::Cube,
    aspect: wgpu::TextureAspect::default(),
    base_mip_level: 1,
    level_count: 1,
    base_array_layer: 0, // this is wrong; setting to 6 gets rid of some errors
    array_layer_count: 6,
});

let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
    layout,
    bindings: &[
        wgpu::Binding {
            binding: 0,
            resource: wgpu::BindingResource::Buffer {
                buffer: &data.buf, // your own uniform data here
                range: 0..data.uniform_buf_size,
            },
        },
        wgpu::Binding {
            binding: 2,
            resource: wgpu::BindingResource::TextureView(&texture_view),
        },
    ],
});
... draw

// these are the vertices used in the old gfx-rs example, i don't really know exactly what i'm doing, but we need some vertices to make our vertex stage go off, so here they are
let vertex_data = [[-1.0, -1.0], [3.0, -1.0], [-1.0, 3.0]];
let buf = device.create_buffer_mapped(len, usage).fill_from_slice(&vertex_data);

rpass.set_pipeline(&pipeline);
rpass.set_bind_group(0, &bind_group, &[]);
rpass.set_vertex_buffers(0, &[(&buf, 0)]);
rpass.draw(0..3 as u32, 0..1);

Also not clear which combo of usage flags i need to get rid of this validation error for the cube texture itself (binding 2 above):

VALIDATION [UNASSIGNED-CoreValidation-Shader-DescriptorTypeMismatch (0)] : Type mismatch on descriptor slot 0.2 (expected `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`) but descriptor of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE

Also metal does not like my fragment shader it seems:

#version 450

layout(set = 0, binding = 2) uniform samplerCube t_cubemap;

layout(location = 0) in vec3 v_uv;
layout(location = 0) out vec4 f_color;

void main() {
    f_color = texture(t_cubemap, v_uv);
}

yields:

[2019-10-31T05:04:20Z ERROR gfx_backend_metal::device] Error compiling the shader CompilationFailed("Compilation failed: \n\nprogram_source:16:118: error: invalid type \'long\' for attribute index expression\nfragment main0_out main0(main0_in in [[stage_in]], texturecube<float> _13 [[texture(0)]], sampler _13Smplr [[sampler(4294967295)]])\n                                                                                                                     ^~~~~~~~~~\n")
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Other', src/libcore/result.rs:999:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

Compiled via:

glslc -fshader-stage=vertex shaders/skybox_vert.glsl -o shaders/bin/skybox_vert.spv
glslc -fshader-stage=fragment shaders/skybox_frag.glsl -o shaders/bin/skybox_frag.spv

It's a pain to comment here, especially when you scroll multiple screens. Please make a PR from your WIP code and we'll continue from there.

Ok I鈥檒l try to get around to this, could you at least comment on shaders? Especially the macos issue is worrisome...

It's all a part of the problem that you used the combined image-sampler in GLSL. There is no such thing in WebGPU, you should be using separate sampler and image bind points, like the other examples do.

Ah k got it, can you paste the relevant sampler line here so I can add it to wip, if you happen to know ? I鈥檓 not familiar with it :)

Edit I ask because I only found the cube sampler in OpenGL docs and adapting the linked old gfx only had that as well, so wasn鈥檛 sure how to proceed.

Here is the piece from the cube example shaders:

layout(set = 0, binding = 1) uniform texture2D t_Color;
layout(set = 0, binding = 2) uniform sampler s_Color;
...
vec4 tex = texture(sampler2D(t_Color, s_Color), v_TexCoord);

Is t_Color the cube map under the hood ? Will the fragment just use the above and v_TexCoord is uv? Did not know you could do that...

If you know what the fragment shader would look like will save me a lot of time if you just paste the full thing here to be honest

Something like this:

#version 450

layout(set = 0, binding = 1) uniform textureCube t_CubeMap;
layout(set = 0, binding = 2) uniform sampler s_CubeMap;

layout(location = 0) in vec3 v_Uv;
layout(location = 0) out vec4 f_Color;

void main() {
    f_Color = texture(samplerCube(t_CubeMap, s_CubeMap), v_Uv);
}

Note that your binding model needs to have entries for the texture and the sampler (in this code under indices 1 and 2).

Yup got it, thanks so much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gzp-crey picture gzp-crey  路  3Comments

m4b picture m4b  路  5Comments

imjasonmiller picture imjasonmiller  路  3Comments

sagacity picture sagacity  路  3Comments

rukai picture rukai  路  5Comments