[vertex shader] void main(float4 pos : POSITION, out float2 color_xy : COLOR0, out float2 color_zw : COLOR1, out float4 position : SV_POSITION) { position = pos; color_xy = float2(0.25, 0.5); color_zw = float2(0.75, 1.0); } [pixel shader] float4 main(float2 color_xy : COLOR0, float2 color_zw : COLOR1) : SV_TARGET { return float4(color_xy, color_zw); } [test] draw quad probe(320, 240) rgba(0.25, 0.5, 0.75, 1.0) % Test handling of arrays in interface blocks [require] shader model >= 4.0 shader model < 6.0 [input layout] [vertex shader] // Rules: // 1. Arrays always start on .x // 2. When placing a scalar or vector, search through the allocated slots for space *vertically* // (So check if you can place at o1.y, then o2.y, o3.y before o1.z, o2.z, etc.) // 3. Elements with different interpolation cannot share a slot. // 4. The first field of a struct is always aligned. struct data { float4 position : SV_Position; // Should be placed in o0 float array1[2] : ARRAY1; // Should be placed in o1.x, o2.x float3 array3[1] : ARRAY3; // Should be placed in o3.xyz float array4[2] : ARRAY4; // Should be placed in o4.x, o5.x nointerpolation float ndata : NDATA; // Should be placed in o6.x uint udata : UDATA; // Should be placed in o6.y float4 data1 : DATA1; // Should be placed in o7.xyzw float3 data2 : DATA2; // Should be placed in o1.yzw float2 data3 : DATA3; // Should be placed in o2.yz float data4 : DATA4; // Should be placed in o4.y float2 data5 : DATA5; // Should be placed in o5.yz float2 data6 : DATA6; // Should be placed in o4.zw float data7 : DATA7; // Should be placed in o2.w float2 data8 : DATA8; // Should be placed in o8.xy float data9 : DATA9; // Should be placed in o8.z (not o3.w) float data10 : DATA10; // Should be placed in o3.w }; void main(uint id : SV_VertexID, out data output) { output.position = float4(id & 1 ? 3 : -1, id & 2 ? -3 : 1, 0, 1); output.array1[0] = 1.0; output.array1[1] = 2.0; output.array3[0] = float3(3.0, 4.0, 5.0); output.array4[0] = 6.0; output.array4[1] = 7.0; output.data1 = float4(8.0, 9.0, 10.0, 11.0); output.data2 = float3(12.0, 13.0, 14.0); output.data3 = float2(15.0, 16.0); output.data4 = 17.0; output.data5 = float2(18.0, 19.0); output.data6 = float2(20.0, 21.0); output.data7 = 22.0; output.data8 = float2(23.0, 24.0); output.data9 = 25.0; output.data10 = 26.0; output.ndata = 27.0; output.udata = 28; } [pixel shader] struct data { float4 position : SV_Position; // v0.xyzw float array1 : ARRAY1; // v1.x float3 data2 : DATA2; // v1.yzw float array2 : ARRAY2; // v2.x float2 data3 : DATA3; // v2.yz float data7 : DATA7; // v2.w float3 array3 : ARRAY3; // v3.xyz float data10 : DATA10; // v3.w float array4 : ARRAY4; // v4.x float data4 : DATA4; // v4.y float2 data6 : DATA6; // v4.zw float array5 : ARRAY5; // v5.x float2 data5 : DATA5; // v5.yz nointerpolation float ndata : NDATA; // v6.x uint udata : UDATA; // v6.y float4 data1 : DATA1; // v7.xyzw float2 data8 : DATA8; // v8.xy float data9 : DATA9; // v8.z }; float4 main(data input) : SV_Target { switch (int(input.position.x)) { case 1: return float4(input.array1, input.data2); case 2: return float4(input.array2, input.data3, input.data7); case 3: return float4(input.array3, input.data10); case 4: return float4(input.array4, input.data4, input.data6); case 5: return float4(input.array5, input.data5, 0); case 6: return float4(input.ndata, input.udata, 0, 0); case 7: return input.data1; case 8: return float4(input.data8, input.data9, 0); default: return 0; } } [test] clear rtv 0 -1.0 -1.0 -1.0 -1.0 todo(mvk & vulkan) draw triangle list 3 todo(mvk) probe (0, 0) rgba ( 0.0, 0.0, 0.0, 0.0) todo(mvk) probe (1, 0) rgba ( 1.0, 12.0, 13.0, 14.0) todo(mvk) probe (2, 0) rgba ( 2.0, 15.0, 16.0, 22.0) todo(mvk) probe (3, 0) rgba ( 3.0, 4.0, 5.0, 26.0) todo(mvk) probe (4, 0) rgba ( 6.0, 17.0, 20.0, 21.0) todo(mvk) probe (5, 0) rgba ( 7.0, 18.0, 19.0, 0.0) todo(mvk) probe (6, 0) rgba (27.0, 28.0, 0.0, 0.0) todo(mvk) probe (7, 0) rgba ( 8.0, 9.0, 10.0, 11.0) todo(mvk) probe (8, 0) rgba (23.0, 24.0, 25.0, 0.0) [require] shader model >= 3.0 [input layout] 0 r32g32-float POSITION [vb 0] -1.0 -1.0 -1.0 3.0 3.0 -1.0 [vertex shader] void main(float2 in_pos : POSITION, out float4 pos : SV_Position, out float4 color : COLOR) { pos = float4(in_pos, 0.0f, 1.0f); color = float4(1.0f, 2.0f, 3.0f, 4.0f); } [pixel shader] % The point of this test is to check that signature masks are handled correctly % when they are not contiguous, so we attempt reading only component .xw from % `color'. This happens when the shader is compiled by native, but not by us, % currently, so it's not very useful for the moment. I'm leaving it anyway % so that it either becomes useful when our HLSL compiler becomes more optimized % or can be eventually rewritten in assembly/bytecode when the shader runner % supports that. float4 main(float4 pos : SV_Position, float4 color : COLOR) : SV_Target { return float4(color.x, 10.0f, 11.0f, color.w); } [test] todo(mvk & sm<4) draw triangle list 3 todo(sm<4) probe (0, 0) rgba (1.0, 10.0, 11.0, 4.0)