how to get render target dimensions dynamically in a Metal fragment shader?
metal
Solution
I'm not aware of a way to directly query the render target for its dimensions from a fragment function.
One technique would be to pass the dimensions in via a buffer. The app code would then fill that buffer using the render target texture's properties. You're already effectively doing that for your `timer` parameter. You'd expand that. For example:
struct params
{
float timer;
uint2 size;
};
Then, replace `float &timer` in your function's parameter list with `params ¶ms`. Replace uses of `timer` in the function body with `params.timer`. Use `params.size` instead of `resolution`.
Your app code would, of course, have to change how it's setting up buffer 0 to be a struct of the appropriate size and layout, with both the timer and render target dimensions stored into it.
I think it will also work to pass the render target texture in as a parameter to the function (via the render command encoder's fragment texture table). Your fragment function would declare another parameter, such as `texture2d<float, access::read> rt [[texture(0)]]`, to receive that texture parameter. Then, you can call `rt.get_width()` and `rt.get_height()` to get its dimensions.
Problem
This Metal shader is based on a tutorial located here http://metalkit.org/2016/10/01/using-metalkit-part-2-3-2.html It draws the yellowish and blue gradient seen in the 3rd image on the page. My goal with this shader was to draw this using a fragment/vertex pair rather than a compute shader. The result of this shader is made visible by a subclass of an MTKView in an MacOS Swift Playground. shader code: ``` #include <metal_stdlib> using namespace metal; struct Vertex { float4 position [[position]]; float4 color; }; vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]]) { Vertex in = vertices[vid]; Vertex out; out.position = float4(in.position); out.color = in.color; return out; } fragment float4 fragment_func(Vertex vert [[stage_in]], constant float &timer [[buffer(0)]]) { float4 fragColor; int width = 400; int height = 400; float2 resolution = float2(width,height); float2 uv = vert.position.xy * 0.5 / resolution; float3 color = mix(float3(1.0, 0.6, 0.1), float3(0.5, 0.8, 1.0), sqrt(1 - uv.y)); fragColor = float4(color,1); return(fragColor); } ``` swift vertex and index code: ``` let vertexData = [ Vertex(pos: [-1.0, -1.0, 0.0, 1.0], col: [1, 0, 0, 1]), Vertex(pos: [ 1.0, -1.0, 0.0, 1.0], col: [0, 1, 0, 1]), Vertex(pos: [ 1.0, 1.0, 0.0, 1.0], col: [0, 0, 1, 1]), Vertex(pos: [-1.0, 1.0, 0.0, 1.0], col: [1, 1, 1, 1]) ] let indexData: [UInt16] = [ 0, 1, 2, 2, 3, 0 ] ``` The dimensions of the final image are hardcoded, 400x400. Is there a way to get the render target dimensions dynamically?