title: Passing textures with UInt8 component type to Metal compute shader
body: <p>I have an image that I generate programmatically and I want to send this image as a texture to a compute shader. The way I generate this image is that I calculate each of the RGBA components as <code>UInt8</code> values, and combine them into a <code>UInt32</code> and store it in the buffer of the image. I do this with the following piece of code:</p>
  
  <pre><code>guard let cgContext = CGContext(data: nil,
                                  width: width,
                                  height: height,
                                  bitsPerComponent: 8,
                                  bytesPerRow: 0,
                                  space: CGColorSpaceCreateDeviceRGB(),
                                  bitmapInfo: RGBA32.bitmapInfo) else {
                                    print("Unable to create CGContext")
                                    return
  }
  
  guard let buffer = cgContext.data else {
    print("Unable to create textures")
    return
  }
  let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
  let heightFloat = Float(height)
  let widthFloat = Float(width)
  for i in 0 ..&lt; height {
    let latitude = Float(i + 1) / heightFloat
    for j in 0 ..&lt; width {
      let longitude = Float(j + 1) / widthFloat
      let x = UInt8(((sin(longitude * Float.pi * 2) * cos(latitude * Float.pi) + 1) / 2) * 255)
      let y = UInt8(((sin(longitude * Float.pi * 2) * sin(latitude * Float.pi) + 1) / 2) * 255)
      let z = UInt8(((cos(latitude * Float.pi) + 1) / 2) * 255)
      let offset = width * i + j
      pixelBuffer[offset] = RGBA32(red: x, green: y, blue: z, alpha: 255)
    }
  }
  
  let coordinateConversionImage = cgContext.makeImage()
  </code></pre>
  
  <p>where <code>RGBA32</code> is a little struct that does the shifting and creating the <code>UInt32</code> value. This image turns out fine as I can convert it to <code>UIImage</code> and save it to my photos library.</p>
  
  <p>The problem arises when I try to send this image as a texture to a compute shader. Below is my shader code:</p>
  
  <pre><code>kernel void updateEnvironmentMap(texture2d&lt;uint, access::read&gt; currentFrameTexture [[texture(0)]],
                                   texture2d&lt;uint, access::read&gt; coordinateConversionTexture [[texture(1)]],
                                   texture2d&lt;uint, access::write&gt; environmentMap [[texture(2)]]
                                   uint2 gid [[thread_position_in_grid]])
  {
    const uint4 pixel = {255, 127, 63, 255};
    environmentMap.write(pixel, gid);
  }
  </code></pre>
  
  <p>The problem with this code is that the type of my textures is <code>uint</code>, which is 32-bits, and I want to generate 32-bit pixels the same way I do on the CPU, by appending 4 8-bit values. However, I can't seem to do that on Metal as there is no <code>byte</code> type that I can just append together and make up a <code>uint32</code>. So, my question is, what is the correct way to handle 2D textures and set 32-bit pixels on a Metal compute shader?</p>
  
  <p>Bonus question: Also, I've seen example shader codes with <code>texture2d&lt;float, access::read&gt;</code> as the input texture type. I'm assuming it represents a value between 0.0 and 1.0 but what advantage that does that have over an unsigned int with values between 0 and 255?</p>
  
  <p>Edit: To clarify, the output texture of the shader, <code>environmentMap</code>, has the exact same properties (width, height, pixelFormat, etc.) as the input textures. Why I think this is counter intuitive is that we are setting a <code>uint4</code> as a pixel, which means it's composed of 4 32-bit values, whereas each pixel should be 32-bits. With this current code, <code>{255, 127, 63, 255}</code> has the exact same result as <code>{2550, 127, 63, 255}</code>, meaning the values somehow get clamped between 0-255 before being written to the output texture. But this is extremely counter-intuitive.</p>