FNA icon indicating copy to clipboard operation
FNA copied to clipboard

Vulkan driver doesnt draw when there are many uniform matrices

Open rds1983 opened this issue 4 months ago • 7 comments

Please, see the attached sample. It tries to draw a 2d image using following shader:

//-----------------------------------------------------------------------------
// SpriteEffect.fx
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------

#include "Macros.fxh"


DECLARE_TEXTURE(Texture, 0);


BEGIN_CONSTANTS
MATRIX_CONSTANTS
    float4x4 MatrixTransform;
    float4x4 OtherTransforms[128];
    int4 OtherTransformsIndices;
END_CONSTANTS


void SpriteVertexShader(inout float2 texCoord : TEXCOORD0,
                        inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);
	
	position = mul(position, OtherTransforms[OtherTransformsIndices.x]);
	position = mul(position, OtherTransforms[OtherTransformsIndices.y]);
	position = mul(position, OtherTransforms[OtherTransformsIndices.z]);
	position = mul(position, OtherTransforms[OtherTransformsIndices.w]);
}


float4 SpritePixelShader(float2 texCoord : TEXCOORD0) : SV_Target0
{
    return tex2D(TextureSampler, texCoord);
}

TECHNIQUE(Default, SpriteVertexShader, SpritePixelShader);

Which is pretty much copy of the original SpriteEffect. The only difference is that it processes input position by OtherTransforms. However all those matrices are set to Identity in the C# part of the sample, so they shouldn't affect the end result.

Unfortunately it draws nothing with the default Vulkan driver: Image

But works correctly when using D311 or OpenGL drivers: Image

Full Sample: ManyMatricesTest.zip

OS: Windows 11 Latest FNA 25.10 from the master branch Latest fnalibs downloaded from fnalibs-daily at 15.10.2025

rds1983 avatar Oct 15 '25 00:10 rds1983

Going to guess that this is either preshaders or the int4 uniform, the floats should be fine but the ints may behave differently. See if a RenderDoc capture shows anything interesting.

flibitijibibo avatar Oct 15 '25 01:10 flibitijibibo

Replacing int4 with float4 didnt help. But the problem goes away if I lower amount of OtherTransforms to 32.

rds1983 avatar Oct 15 '25 01:10 rds1983

Interesting - this may be SDL_GPU uploads; RenderDoc will definitely show if we're uploading the full 4x4 buffer when it's higher than 32 elements.

flibitijibibo avatar Oct 15 '25 01:10 flibitijibibo

Preshader:

            mul c516.x, c0.x, (4)
            mul c517.x, c0.y, (4)
            mul c518.x, c0.z, (4)
            mul c519.x, c0.w, (4)

GLSL output...

            #version 110
            uniform vec4 vs_uniforms_vec4[520];
            uniform float vpFlip;
            vec4 vs_r0;
            vec4 vs_r1;
            ivec4 vs_a0;
            #define ARRAYBASE_0 0
            #define vs_c0 vs_uniforms_vec4[0]
            #define vs_c1 vs_uniforms_vec4[1]
            #define vs_c2 vs_uniforms_vec4[2]
            #define vs_c3 vs_uniforms_vec4[3]
            #define vs_c512 vs_uniforms_vec4[512]
            #define vs_c513 vs_uniforms_vec4[513]
            #define vs_c514 vs_uniforms_vec4[514]
            #define vs_c515 vs_uniforms_vec4[515]
            #define vs_c516 vs_uniforms_vec4[516]
            #define vs_c517 vs_uniforms_vec4[517]
            #define vs_c518 vs_uniforms_vec4[518]
            #define vs_c519 vs_uniforms_vec4[519]
            attribute vec4 vs_v0;
            attribute vec4 vs_v1;
            #define vs_o0 gl_TexCoord[0]
            #define vs_o1 gl_Position
            
            void main()
            {
                vs_r0.x = dot(vs_v1, vs_c512);
                vs_r0.y = dot(vs_v1, vs_c513);
                vs_r0.z = dot(vs_v1, vs_c514);
                vs_r0.w = dot(vs_v1, vs_c515);
                vs_a0.w = int(floor(abs(vs_c516.x) + 0.5) * sign(vs_c516.x));
                vs_r1.x = dot(vs_r0, vs_uniforms_vec4[ARRAYBASE_0 + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c516.x) + 0.5) * sign(vs_c516.x));
                vs_r1.y = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 1) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c516.x) + 0.5) * sign(vs_c516.x));
                vs_r1.z = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 2) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c516.x) + 0.5) * sign(vs_c516.x));
                vs_r1.w = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 3) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c517.x) + 0.5) * sign(vs_c517.x));
                vs_r0.x = dot(vs_r1, vs_uniforms_vec4[ARRAYBASE_0 + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c517.x) + 0.5) * sign(vs_c517.x));
                vs_r0.y = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 1) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c517.x) + 0.5) * sign(vs_c517.x));
                vs_r0.z = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 2) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c517.x) + 0.5) * sign(vs_c517.x));
                vs_r0.w = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 3) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c518.x) + 0.5) * sign(vs_c518.x));
                vs_r1.x = dot(vs_r0, vs_uniforms_vec4[ARRAYBASE_0 + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c518.x) + 0.5) * sign(vs_c518.x));
                vs_r1.y = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 1) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c518.x) + 0.5) * sign(vs_c518.x));
                vs_r1.z = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 2) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c518.x) + 0.5) * sign(vs_c518.x));
                vs_r1.w = dot(vs_r0, vs_uniforms_vec4[(ARRAYBASE_0 + 3) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c519.x) + 0.5) * sign(vs_c519.x));
                vs_o1.x = dot(vs_r1, vs_uniforms_vec4[ARRAYBASE_0 + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c519.x) + 0.5) * sign(vs_c519.x));
                vs_o1.y = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 1) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c519.x) + 0.5) * sign(vs_c519.x));
                vs_o1.z = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 2) + vs_a0.w]);
                vs_a0.w = int(floor(abs(vs_c519.x) + 0.5) * sign(vs_c519.x));
                vs_o1.w = dot(vs_r1, vs_uniforms_vec4[(ARRAYBASE_0 + 3) + vs_a0.w]);
                vs_o0.xy = vs_v0.xy;
                gl_Position.y = gl_Position.y * vpFlip;
                gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;

SPIR-V

            ; SPIR-V
            ; Version: 1.0
            ; Generator: Khronos; 0
            ; Bound: 368
            ; Schema: 0
            OpCapability Shader
            %59 = OpExtInstImport "GLSL.std.450"
            OpMemoryModel Logical Simple
            OpEntryPoint Vertex %ShaderFunction3 "ShaderFunction3" %vs_v0 %vs_v1 %vs_o0 %vs_o1
            OpName %ShaderFunction3 "ShaderFunction3"
            OpName %vs_r0 "vs_r0"
            OpName %vs_r1 "vs_r1"
            OpName %vs_a0 "vs_a0"
            OpName %c0 "c0"
            OpName %c1 "c1"
            OpName %c2 "c2"
            OpName %c3 "c3"
            OpName %c512 "c512"
            OpName %c513 "c513"
            OpName %c514 "c514"
            OpName %c515 "c515"
            OpName %c516 "c516"
            OpName %c517 "c517"
            OpName %c518 "c518"
            OpName %c519 "c519"
            OpName %vs_v0 "vs_v0"
            OpName %vs_v1 "vs_v1"
            OpName %vs_o0 "vs_o0"
            OpName %vs_o1 "vs_o1"
            OpName %vs_uniforms "vs_uniforms"
            OpDecorate %vs_v0 Location 0
            OpDecorate %vs_v1 Location 1
            OpDecorate %vs_o0 Location 3735928559
            OpDecorate %vs_o1 BuiltIn Position
            OpDecorate %_struct_366 Block
            OpDecorate %vs_uniforms DescriptorSet 1
            OpDecorate %vs_uniforms Binding 0
            OpDecorate %_arr_v4float_int_520 ArrayStride 16
            OpMemberDecorate %_struct_366 0 Offset 0
            %void = OpTypeVoid
            %3 = OpTypeFunction %void
            %float = OpTypeFloat 32
            %v4float = OpTypeVector %float 4
            %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
            %int = OpTypeInt 32 1
            %v4int = OpTypeVector %int 4
            %_ptr_Private_int = OpTypePointer Private %int
            %int_3 = OpConstant %int 3
            %int_1 = OpConstant %int 1
            %int_2 = OpConstant %int 2
            %_ptr_Private_v4float = OpTypePointer Private %v4float
            %vs_r0 = OpVariable %_ptr_Private_v4float Private
            %vs_r1 = OpVariable %_ptr_Private_v4float Private
            %_ptr_Private_v4int = OpTypePointer Private %v4int
            %vs_a0 = OpVariable %_ptr_Private_v4int Private
            %c0 = OpConstant %int 0
            %c1 = OpConstant %int 0
            %c2 = OpConstant %int 0
            %c3 = OpConstant %int 0
            %c512 = OpConstant %int 512
            %c513 = OpConstant %int 513
            %c514 = OpConstant %int 514
            %c515 = OpConstant %int 515
            %c516 = OpConstant %int 516
            %c517 = OpConstant %int 517
            %c518 = OpConstant %int 518
            %c519 = OpConstant %int 519
            %_ptr_Input_v4float = OpTypePointer Input %v4float
            %_ptr_Input_v4int = OpTypePointer Input %v4int
            %uint = OpTypeInt 32 0
            %v4uint = OpTypeVector %uint 4
            %_ptr_Input_v4uint = OpTypePointer Input %v4uint
            %vs_v0 = OpVariable %_ptr_Input_v4float Input
            %vs_v1 = OpVariable %_ptr_Input_v4float Input
            %_ptr_Output_v4float = OpTypePointer Output %v4float
            %vs_o0 = OpVariable %_ptr_Output_v4float Output
            %vs_o1 = OpVariable %_ptr_Output_v4float Output
            %int_520 = OpConstant %int 520
            %_arr_v4float_int_520 = OpTypeArray %v4float %int_520
            %int_0 = OpConstant %int 0
            %_struct_366 = OpTypeStruct %_arr_v4float_int_520
            %_ptr_Uniform__struct_366 = OpTypePointer Uniform %_struct_366
            %vs_uniforms = OpVariable %_ptr_Uniform__struct_366 Uniform
            %ShaderFunction3 = OpFunction %void None %3
            %4 = OpLabel
            %11 = OpLoad %v4float %vs_v1
            %12 = OpCopyObject %v4float %11
            %16 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c512
            %18 = OpLoad %v4float %16
            %19 = OpDot %float %12 %18
            %20 = OpCompositeConstruct %v4float %19 %19 %19 %19
            %23 = OpLoad %v4float %vs_r0
            %22 = OpVectorShuffle %v4float %20 %23 0 5 6 7
            OpStore %vs_r0 %22
            %24 = OpLoad %v4float %vs_v1
            %25 = OpCopyObject %v4float %24
            %27 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c513
            %28 = OpLoad %v4float %27
            %29 = OpDot %float %25 %28
            %30 = OpCompositeConstruct %v4float %29 %29 %29 %29
            %32 = OpLoad %v4float %vs_r0
            %31 = OpVectorShuffle %v4float %30 %32 4 1 6 7
            OpStore %vs_r0 %31
            %33 = OpLoad %v4float %vs_v1
            %34 = OpCopyObject %v4float %33
            %36 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c514
            %37 = OpLoad %v4float %36
            %38 = OpDot %float %34 %37
            %39 = OpCompositeConstruct %v4float %38 %38 %38 %38
            %41 = OpLoad %v4float %vs_r0
            %40 = OpVectorShuffle %v4float %39 %41 4 5 2 7
            OpStore %vs_r0 %40
            %42 = OpLoad %v4float %vs_v1
            %43 = OpCopyObject %v4float %42
            %45 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c515
            %46 = OpLoad %v4float %45
            %47 = OpDot %float %43 %46
            %48 = OpCompositeConstruct %v4float %47 %47 %47 %47
            %50 = OpLoad %v4float %vs_r0
            %49 = OpVectorShuffle %v4float %48 %50 4 5 6 3
            OpStore %vs_r0 %49
            %52 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c516
            %53 = OpLoad %v4float %52
            %54 = OpVectorShuffle %v4float %53 %53 0 0 0 0
            %55 = OpExtInst %v4float %59 Round %54
            %58 = OpConvertFToS %v4int %55
            %62 = OpLoad %v4int %vs_a0
            %61 = OpVectorShuffle %v4int %58 %62 4 5 6 3
            OpStore %vs_a0 %61
            %63 = OpLoad %v4float %vs_r0
            %67 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %68 = OpLoad %int %67
            %69 = OpIAdd %int %68 %c0
            %70 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %69
            %71 = OpLoad %v4float %70
            %72 = OpDot %float %63 %71
            %73 = OpCompositeConstruct %v4float %72 %72 %72 %72
            %76 = OpLoad %v4float %vs_r1
            %75 = OpVectorShuffle %v4float %73 %76 0 5 6 7
            OpStore %vs_r1 %75
            %77 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c516
            %78 = OpLoad %v4float %77
            %79 = OpVectorShuffle %v4float %78 %78 0 0 0 0
            %80 = OpExtInst %v4float %59 Round %79
            %81 = OpConvertFToS %v4int %80
            %83 = OpLoad %v4int %vs_a0
            %82 = OpVectorShuffle %v4int %81 %83 4 5 6 3
            OpStore %vs_a0 %82
            %84 = OpLoad %v4float %vs_r0
            %86 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %87 = OpLoad %int %86
            %88 = OpIAdd %int %87 %c1
            %90 = OpIAdd %int %88 %int_1
            %91 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %90
            %92 = OpLoad %v4float %91
            %93 = OpDot %float %84 %92
            %94 = OpCompositeConstruct %v4float %93 %93 %93 %93
            %96 = OpLoad %v4float %vs_r1
            %95 = OpVectorShuffle %v4float %94 %96 4 1 6 7
            OpStore %vs_r1 %95
            %97 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c516
            %98 = OpLoad %v4float %97
            %99 = OpVectorShuffle %v4float %98 %98 0 0 0 0
            %100 = OpExtInst %v4float %59 Round %99
            %101 = OpConvertFToS %v4int %100
            %103 = OpLoad %v4int %vs_a0
            %102 = OpVectorShuffle %v4int %101 %103 4 5 6 3
            OpStore %vs_a0 %102
            %104 = OpLoad %v4float %vs_r0
            %106 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %107 = OpLoad %int %106
            %108 = OpIAdd %int %107 %c2
            %110 = OpIAdd %int %108 %int_2
            %111 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %110
            %112 = OpLoad %v4float %111
            %113 = OpDot %float %104 %112
            %114 = OpCompositeConstruct %v4float %113 %113 %113 %113
            %116 = OpLoad %v4float %vs_r1
            %115 = OpVectorShuffle %v4float %114 %116 4 5 2 7
            OpStore %vs_r1 %115
            %117 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c516
            %118 = OpLoad %v4float %117
            %119 = OpVectorShuffle %v4float %118 %118 0 0 0 0
            %120 = OpExtInst %v4float %59 Round %119
            %121 = OpConvertFToS %v4int %120
            %123 = OpLoad %v4int %vs_a0
            %122 = OpVectorShuffle %v4int %121 %123 4 5 6 3
            OpStore %vs_a0 %122
            %124 = OpLoad %v4float %vs_r0
            %126 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %127 = OpLoad %int %126
            %128 = OpIAdd %int %127 %c3
            %129 = OpIAdd %int %128 %int_3
            %130 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %129
            %131 = OpLoad %v4float %130
            %132 = OpDot %float %124 %131
            %133 = OpCompositeConstruct %v4float %132 %132 %132 %132
            %135 = OpLoad %v4float %vs_r1
            %134 = OpVectorShuffle %v4float %133 %135 4 5 6 3
            OpStore %vs_r1 %134
            %137 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c517
            %138 = OpLoad %v4float %137
            %139 = OpVectorShuffle %v4float %138 %138 0 0 0 0
            %140 = OpExtInst %v4float %59 Round %139
            %141 = OpConvertFToS %v4int %140
            %143 = OpLoad %v4int %vs_a0
            %142 = OpVectorShuffle %v4int %141 %143 4 5 6 3
            OpStore %vs_a0 %142
            %144 = OpLoad %v4float %vs_r1
            %145 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %146 = OpLoad %int %145
            %147 = OpIAdd %int %146 %c0
            %148 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %147
            %149 = OpLoad %v4float %148
            %150 = OpDot %float %144 %149
            %151 = OpCompositeConstruct %v4float %150 %150 %150 %150
            %153 = OpLoad %v4float %vs_r0
            %152 = OpVectorShuffle %v4float %151 %153 0 5 6 7
            OpStore %vs_r0 %152
            %154 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c517
            %155 = OpLoad %v4float %154
            %156 = OpVectorShuffle %v4float %155 %155 0 0 0 0
            %157 = OpExtInst %v4float %59 Round %156
            %158 = OpConvertFToS %v4int %157
            %160 = OpLoad %v4int %vs_a0
            %159 = OpVectorShuffle %v4int %158 %160 4 5 6 3
            OpStore %vs_a0 %159
            %161 = OpLoad %v4float %vs_r1
            %162 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %163 = OpLoad %int %162
            %164 = OpIAdd %int %163 %c1
            %165 = OpIAdd %int %164 %int_1
            %166 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %165
            %167 = OpLoad %v4float %166
            %168 = OpDot %float %161 %167
            %169 = OpCompositeConstruct %v4float %168 %168 %168 %168
            %171 = OpLoad %v4float %vs_r0
            %170 = OpVectorShuffle %v4float %169 %171 4 1 6 7
            OpStore %vs_r0 %170
            %172 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c517
            %173 = OpLoad %v4float %172
            %174 = OpVectorShuffle %v4float %173 %173 0 0 0 0
            %175 = OpExtInst %v4float %59 Round %174
            %176 = OpConvertFToS %v4int %175
            %178 = OpLoad %v4int %vs_a0
            %177 = OpVectorShuffle %v4int %176 %178 4 5 6 3
            OpStore %vs_a0 %177
            %179 = OpLoad %v4float %vs_r1
            %180 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %181 = OpLoad %int %180
            %182 = OpIAdd %int %181 %c2
            %183 = OpIAdd %int %182 %int_2
            %184 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %183
            %185 = OpLoad %v4float %184
            %186 = OpDot %float %179 %185
            %187 = OpCompositeConstruct %v4float %186 %186 %186 %186
            %189 = OpLoad %v4float %vs_r0
            %188 = OpVectorShuffle %v4float %187 %189 4 5 2 7
            OpStore %vs_r0 %188
            %190 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c517
            %191 = OpLoad %v4float %190
            %192 = OpVectorShuffle %v4float %191 %191 0 0 0 0
            %193 = OpExtInst %v4float %59 Round %192
            %194 = OpConvertFToS %v4int %193
            %196 = OpLoad %v4int %vs_a0
            %195 = OpVectorShuffle %v4int %194 %196 4 5 6 3
            OpStore %vs_a0 %195
            %197 = OpLoad %v4float %vs_r1
            %198 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %199 = OpLoad %int %198
            %200 = OpIAdd %int %199 %c3
            %201 = OpIAdd %int %200 %int_3
            %202 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %201
            %203 = OpLoad %v4float %202
            %204 = OpDot %float %197 %203
            %205 = OpCompositeConstruct %v4float %204 %204 %204 %204
            %207 = OpLoad %v4float %vs_r0
            %206 = OpVectorShuffle %v4float %205 %207 4 5 6 3
            OpStore %vs_r0 %206
            %209 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c518
            %210 = OpLoad %v4float %209
            %211 = OpVectorShuffle %v4float %210 %210 0 0 0 0
            %212 = OpExtInst %v4float %59 Round %211
            %213 = OpConvertFToS %v4int %212
            %215 = OpLoad %v4int %vs_a0
            %214 = OpVectorShuffle %v4int %213 %215 4 5 6 3
            OpStore %vs_a0 %214
            %216 = OpLoad %v4float %vs_r0
            %217 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %218 = OpLoad %int %217
            %219 = OpIAdd %int %218 %c0
            %220 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %219
            %221 = OpLoad %v4float %220
            %222 = OpDot %float %216 %221
            %223 = OpCompositeConstruct %v4float %222 %222 %222 %222
            %225 = OpLoad %v4float %vs_r1
            %224 = OpVectorShuffle %v4float %223 %225 0 5 6 7
            OpStore %vs_r1 %224
            %226 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c518
            %227 = OpLoad %v4float %226
            %228 = OpVectorShuffle %v4float %227 %227 0 0 0 0
            %229 = OpExtInst %v4float %59 Round %228
            %230 = OpConvertFToS %v4int %229
            %232 = OpLoad %v4int %vs_a0
            %231 = OpVectorShuffle %v4int %230 %232 4 5 6 3
            OpStore %vs_a0 %231
            %233 = OpLoad %v4float %vs_r0
            %234 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %235 = OpLoad %int %234
            %236 = OpIAdd %int %235 %c1
            %237 = OpIAdd %int %236 %int_1
            %238 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %237
            %239 = OpLoad %v4float %238
            %240 = OpDot %float %233 %239
            %241 = OpCompositeConstruct %v4float %240 %240 %240 %240
            %243 = OpLoad %v4float %vs_r1
            %242 = OpVectorShuffle %v4float %241 %243 4 1 6 7
            OpStore %vs_r1 %242
            %244 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c518
            %245 = OpLoad %v4float %244
            %246 = OpVectorShuffle %v4float %245 %245 0 0 0 0
            %247 = OpExtInst %v4float %59 Round %246
            %248 = OpConvertFToS %v4int %247
            %250 = OpLoad %v4int %vs_a0
            %249 = OpVectorShuffle %v4int %248 %250 4 5 6 3
            OpStore %vs_a0 %249
            %251 = OpLoad %v4float %vs_r0
            %252 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %253 = OpLoad %int %252
            %254 = OpIAdd %int %253 %c2
            %255 = OpIAdd %int %254 %int_2
            %256 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %255
            %257 = OpLoad %v4float %256
            %258 = OpDot %float %251 %257
            %259 = OpCompositeConstruct %v4float %258 %258 %258 %258
            %261 = OpLoad %v4float %vs_r1
            %260 = OpVectorShuffle %v4float %259 %261 4 5 2 7
            OpStore %vs_r1 %260
            %262 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c518
            %263 = OpLoad %v4float %262
            %264 = OpVectorShuffle %v4float %263 %263 0 0 0 0
            %265 = OpExtInst %v4float %59 Round %264
            %266 = OpConvertFToS %v4int %265
            %268 = OpLoad %v4int %vs_a0
            %267 = OpVectorShuffle %v4int %266 %268 4 5 6 3
            OpStore %vs_a0 %267
            %269 = OpLoad %v4float %vs_r0
            %270 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %271 = OpLoad %int %270
            %272 = OpIAdd %int %271 %c3
            %273 = OpIAdd %int %272 %int_3
            %274 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %273
            %275 = OpLoad %v4float %274
            %276 = OpDot %float %269 %275
            %277 = OpCompositeConstruct %v4float %276 %276 %276 %276
            %279 = OpLoad %v4float %vs_r1
            %278 = OpVectorShuffle %v4float %277 %279 4 5 6 3
            OpStore %vs_r1 %278
            %281 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c519
            %282 = OpLoad %v4float %281
            %283 = OpVectorShuffle %v4float %282 %282 0 0 0 0
            %284 = OpExtInst %v4float %59 Round %283
            %285 = OpConvertFToS %v4int %284
            %287 = OpLoad %v4int %vs_a0
            %286 = OpVectorShuffle %v4int %285 %287 4 5 6 3
            OpStore %vs_a0 %286
            %288 = OpLoad %v4float %vs_r1
            %289 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %290 = OpLoad %int %289
            %291 = OpIAdd %int %290 %c0
            %292 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %291
            %293 = OpLoad %v4float %292
            %294 = OpDot %float %288 %293
            %295 = OpCompositeConstruct %v4float %294 %294 %294 %294
            %297 = OpLoad %v4float %vs_o1
            %296 = OpVectorShuffle %v4float %295 %297 0 5 6 7
            OpStore %vs_o1 %296
            %298 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c519
            %299 = OpLoad %v4float %298
            %300 = OpVectorShuffle %v4float %299 %299 0 0 0 0
            %301 = OpExtInst %v4float %59 Round %300
            %302 = OpConvertFToS %v4int %301
            %304 = OpLoad %v4int %vs_a0
            %303 = OpVectorShuffle %v4int %302 %304 4 5 6 3
            OpStore %vs_a0 %303
            %305 = OpLoad %v4float %vs_r1
            %306 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %307 = OpLoad %int %306
            %308 = OpIAdd %int %307 %c1
            %309 = OpIAdd %int %308 %int_1
            %310 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %309
            %311 = OpLoad %v4float %310
            %312 = OpDot %float %305 %311
            %313 = OpCompositeConstruct %v4float %312 %312 %312 %312
            %315 = OpLoad %v4float %vs_o1
            %314 = OpVectorShuffle %v4float %313 %315 4 1 6 7
            OpStore %vs_o1 %314
            %316 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c519
            %317 = OpLoad %v4float %316
            %318 = OpVectorShuffle %v4float %317 %317 0 0 0 0
            %319 = OpExtInst %v4float %59 Round %318
            %320 = OpConvertFToS %v4int %319
            %322 = OpLoad %v4int %vs_a0
            %321 = OpVectorShuffle %v4int %320 %322 4 5 6 3
            OpStore %vs_a0 %321
            %323 = OpLoad %v4float %vs_r1
            %324 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %325 = OpLoad %int %324
            %326 = OpIAdd %int %325 %c2
            %327 = OpIAdd %int %326 %int_2
            %328 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %327
            %329 = OpLoad %v4float %328
            %330 = OpDot %float %323 %329
            %331 = OpCompositeConstruct %v4float %330 %330 %330 %330
            %333 = OpLoad %v4float %vs_o1
            %332 = OpVectorShuffle %v4float %331 %333 4 5 2 7
            OpStore %vs_o1 %332
            %334 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %c519
            %335 = OpLoad %v4float %334
            %336 = OpVectorShuffle %v4float %335 %335 0 0 0 0
            %337 = OpExtInst %v4float %59 Round %336
            %338 = OpConvertFToS %v4int %337
            %340 = OpLoad %v4int %vs_a0
            %339 = OpVectorShuffle %v4int %338 %340 4 5 6 3
            OpStore %vs_a0 %339
            %341 = OpLoad %v4float %vs_r1
            %342 = OpAccessChain %_ptr_Private_int %vs_a0 %int_3
            %343 = OpLoad %int %342
            %344 = OpIAdd %int %343 %c3
            %345 = OpIAdd %int %344 %int_3
            %346 = OpAccessChain %_ptr_Uniform_v4float %vs_uniforms %int_0 %345
            %347 = OpLoad %v4float %346
            %348 = OpDot %float %341 %347
            %349 = OpCompositeConstruct %v4float %348 %348 %348 %348
            %351 = OpLoad %v4float %vs_o1
            %350 = OpVectorShuffle %v4float %349 %351 4 5 6 3
            OpStore %vs_o1 %350
            %352 = OpLoad %v4float %vs_v0
            %353 = OpCopyObject %v4float %352
            %355 = OpLoad %v4float %vs_o0
            %354 = OpVectorShuffle %v4float %353 %355 0 1 6 7
            OpStore %vs_o0 %354
            OpReturn
            OpFunctionEnd

flibitijibibo avatar Oct 15 '25 02:10 flibitijibibo

In Discord we determined that the cause is SDL_GPU having a 4KB limit on uniform buffer size, the matrix array alone is 8k... this is an SDL issue, we likely need to set the internal max to 16KB instead.

flibitijibibo avatar Oct 15 '25 02:10 flibitijibibo

Is there an SDL issue open for this yet? I didn't find one

kg avatar Nov 25 '25 17:11 kg

Not yet - I think we ultimately decided to keep the limit but add validation and expose a property to set the limit, since D3D9 needs 64K(!) to support the max constant register size.

flibitijibibo avatar Nov 25 '25 17:11 flibitijibibo