@@ -177,6 +177,22 @@ typedef struct SpvReflectPrvString {
177177} SpvReflectPrvString ;
178178// clang-format on
179179
180+ // clang-format off
181+ // There are a limit set of instructions that can touch an OpVariable,
182+ // these are represented here with how it was accessed
183+ // Examples:
184+ // OpImageRead -> OpLoad -> OpVariable
185+ // OpImageWrite -> OpLoad -> OpVariable
186+ // OpStore -> OpAccessChain -> OpVariable
187+ // OpAtomicIAdd -> OpAccessChain -> OpVariable
188+ // OpAtomicLoad -> OpImageTexelPointer -> OpVariable
189+ typedef struct SpvReflectPrvAccessedVariable {
190+ uint32_t result_id ;
191+ uint32_t variable_ptr ;
192+ SpvReflectAccessFlags access_flags ;
193+ } SpvReflectPrvAccessedVariable ;
194+ // clang-format on
195+
180196// clang-format off
181197typedef struct SpvReflectPrvFunction {
182198 uint32_t id ;
@@ -185,6 +201,8 @@ typedef struct SpvReflectPrvFunction {
185201 struct SpvReflectPrvFunction * * callee_ptrs ;
186202 uint32_t accessed_ptr_count ;
187203 uint32_t * accessed_ptrs ;
204+ uint32_t accessed_variable_ptr_count ;
205+ SpvReflectPrvAccessedVariable * accessed_variable_ptrs ;
188206} SpvReflectPrvFunction ;
189207// clang-format on
190208
@@ -685,6 +703,7 @@ static void DestroyParser(SpvReflectPrvParser* p_parser)
685703 SafeFree (p_parser -> functions [i ].callees );
686704 SafeFree (p_parser -> functions [i ].callee_ptrs );
687705 SafeFree (p_parser -> functions [i ].accessed_ptrs );
706+ SafeFree (p_parser -> functions [i ].accessed_variable_ptrs );
688707 }
689708
690709 // Free access chains
@@ -1160,6 +1179,7 @@ static SpvReflectResult ParseFunction(
11601179 p_func -> callee_count = 0 ;
11611180 p_func -> accessed_ptr_count = 0 ;
11621181
1182+ // First get count to know how much to allocate
11631183 for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
11641184 SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
11651185 if (p_node -> op == SpvOpFunctionEnd ) {
@@ -1207,10 +1227,17 @@ static SpvReflectResult ParseFunction(
12071227 if (IsNull (p_func -> accessed_ptrs )) {
12081228 return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
12091229 }
1230+
1231+ p_func -> accessed_variable_ptrs = (SpvReflectPrvAccessedVariable * )calloc (
1232+ p_func -> accessed_ptr_count , sizeof (* (p_func -> accessed_variable_ptrs )));
1233+ if (IsNull (p_func -> accessed_variable_ptrs )) {
1234+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
1235+ }
12101236 }
12111237
12121238 p_func -> callee_count = 0 ;
12131239 p_func -> accessed_ptr_count = 0 ;
1240+ // Now have allocation, fill in values
12141241 for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
12151242 SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
12161243 if (p_node -> op == SpvOpFunctionEnd ) {
@@ -1221,26 +1248,73 @@ static SpvReflectResult ParseFunction(
12211248 CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
12221249 p_func -> callees [p_func -> callee_count ]);
12231250 (++ p_func -> callee_count );
1224- }
1225- break ;
1226- case SpvOpLoad :
1251+ } break ;
12271252 case SpvOpAccessChain :
12281253 case SpvOpInBoundsAccessChain :
12291254 case SpvOpPtrAccessChain :
12301255 case SpvOpArrayLength :
12311256 case SpvOpGenericPtrMemSemantics :
1232- case SpvOpInBoundsPtrAccessChain :
1257+ case SpvOpInBoundsPtrAccessChain : {
1258+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
1259+ p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1260+
1261+ CHECKED_READU32 (
1262+ p_parser , p_node -> word_offset + 3 ,
1263+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1264+ .variable_ptr );
1265+ // Need to track Result ID as not sure there has been any memory access
1266+ // through here yet
1267+ CHECKED_READU32 (
1268+ p_parser , p_node -> word_offset + 2 ,
1269+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1270+ .result_id );
1271+ (++ p_func -> accessed_ptr_count );
1272+ } break ;
1273+ case SpvOpLoad : {
1274+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
1275+ p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1276+
1277+ CHECKED_READU32 (
1278+ p_parser , p_node -> word_offset + 3 ,
1279+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1280+ .variable_ptr );
1281+ CHECKED_READU32 (
1282+ p_parser , p_node -> word_offset + 2 ,
1283+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1284+ .result_id );
1285+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1286+ .access_flags = SPV_REFLECT_ACCESS_READ ;
1287+ (++ p_func -> accessed_ptr_count );
1288+ } break ;
12331289 case SpvOpImageTexelPointer :
12341290 {
12351291 CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
12361292 p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1293+
1294+ CHECKED_READU32 (
1295+ p_parser , p_node -> word_offset + 3 ,
1296+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1297+ .variable_ptr );
1298+ CHECKED_READU32 (
1299+ p_parser , p_node -> word_offset + 2 ,
1300+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1301+ .result_id );
1302+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1303+ .access_flags = SPV_REFLECT_ACCESS_ATOMIC ;
12371304 (++ p_func -> accessed_ptr_count );
12381305 }
12391306 break ;
12401307 case SpvOpStore :
12411308 {
12421309 CHECKED_READU32 (p_parser , p_node -> word_offset + 2 ,
12431310 p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1311+
1312+ CHECKED_READU32 (
1313+ p_parser , p_node -> word_offset + 2 ,
1314+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1315+ .variable_ptr );
1316+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1317+ .access_flags = SPV_REFLECT_ACCESS_WRITE ;
12441318 (++ p_func -> accessed_ptr_count );
12451319 }
12461320 break ;
@@ -1259,6 +1333,64 @@ static SpvReflectResult ParseFunction(
12591333 }
12601334 }
12611335
1336+ // Apply the SpvReflectAccessFlags to all things touching an OpVariable
1337+ for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
1338+ SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
1339+ if (p_node -> op == SpvOpFunctionEnd ) {
1340+ break ;
1341+ }
1342+ // These are memory accesses instruction
1343+ uint32_t memory_access_ptr = 0 ;
1344+ SpvReflectAccessFlags memory_access_type = SPV_REFLECT_ACCESS_NONE ;
1345+ switch (p_node -> op ) {
1346+ case SpvOpLoad : {
1347+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , memory_access_ptr );
1348+ memory_access_type = SPV_REFLECT_ACCESS_READ ;
1349+ } break ;
1350+ case SpvOpImageWrite :
1351+ case SpvOpStore : {
1352+ CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , memory_access_ptr );
1353+ memory_access_type = SPV_REFLECT_ACCESS_WRITE ;
1354+ } break ;
1355+ case SpvOpImageTexelPointer :
1356+ case SpvOpAtomicLoad :
1357+ case SpvOpAtomicExchange :
1358+ case SpvOpAtomicCompareExchange :
1359+ case SpvOpAtomicIIncrement :
1360+ case SpvOpAtomicIDecrement :
1361+ case SpvOpAtomicIAdd :
1362+ case SpvOpAtomicISub :
1363+ case SpvOpAtomicSMin :
1364+ case SpvOpAtomicUMin :
1365+ case SpvOpAtomicSMax :
1366+ case SpvOpAtomicUMax :
1367+ case SpvOpAtomicAnd :
1368+ case SpvOpAtomicOr :
1369+ case SpvOpAtomicXor :
1370+ case SpvOpAtomicFMinEXT :
1371+ case SpvOpAtomicFMaxEXT :
1372+ case SpvOpAtomicFAddEXT : {
1373+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , memory_access_ptr );
1374+ memory_access_type = SPV_REFLECT_ACCESS_ATOMIC ;
1375+ } break ;
1376+ case SpvOpAtomicStore : {
1377+ CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , memory_access_ptr );
1378+ memory_access_type = SPV_REFLECT_ACCESS_ATOMIC ;
1379+ } break ;
1380+ default :
1381+ break ;
1382+ }
1383+
1384+ if (memory_access_ptr == 0 ) {
1385+ continue ;
1386+ }
1387+ for (uint32_t k = 0 ; k < p_func -> accessed_ptr_count ; k ++ ) {
1388+ if (p_func -> accessed_variable_ptrs [k ].result_id == memory_access_ptr ) {
1389+ p_func -> accessed_variable_ptrs [k ].access_flags |= memory_access_type ;
1390+ }
1391+ }
1392+ }
1393+
12621394 if (p_func -> callee_count > 0 ) {
12631395 qsort (p_func -> callees , p_func -> callee_count ,
12641396 sizeof (* (p_func -> callees )), SortCompareUint32 );
@@ -1270,6 +1402,7 @@ static SpvReflectResult ParseFunction(
12701402 qsort (p_func -> accessed_ptrs , p_func -> accessed_ptr_count ,
12711403 sizeof (* (p_func -> accessed_ptrs )), SortCompareUint32 );
12721404 }
1405+ p_func -> accessed_variable_ptr_count = p_func -> accessed_ptr_count ;
12731406 p_func -> accessed_ptr_count = (uint32_t )DedupSortedUint32 (p_func -> accessed_ptrs ,
12741407 p_func -> accessed_ptr_count );
12751408
@@ -3317,24 +3450,35 @@ static SpvReflectResult ParseStaticallyUsedResources(
33173450 called_function_count = DedupSortedUint32 (p_called_functions , called_function_count );
33183451
33193452 uint32_t used_variable_count = 0 ;
3453+ uint32_t used_acessed_count = 0 ;
33203454 for (size_t i = 0 , j = 0 ; i < called_function_count ; ++ i ) {
33213455 // No need to bounds check j because a missing ID issue would have been
33223456 // found during TraverseCallGraph
33233457 while (p_parser -> functions [j ].id != p_called_functions [i ]) {
33243458 ++ j ;
33253459 }
33263460 used_variable_count += p_parser -> functions [j ].accessed_ptr_count ;
3461+ used_acessed_count += p_parser -> functions [j ].accessed_variable_ptr_count ;
33273462 }
33283463 uint32_t * used_variables = NULL ;
3464+ SpvReflectPrvAccessedVariable * used_accesses = NULL ;
33293465 if (used_variable_count > 0 ) {
33303466 used_variables = (uint32_t * )calloc (used_variable_count ,
33313467 sizeof (* used_variables ));
33323468 if (IsNull (used_variables )) {
33333469 SafeFree (p_called_functions );
33343470 return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
33353471 }
3472+
3473+ used_accesses = (SpvReflectPrvAccessedVariable * )calloc (
3474+ used_acessed_count , sizeof (SpvReflectPrvAccessedVariable ));
3475+ if (IsNull (used_accesses )) {
3476+ SafeFree (p_called_functions );
3477+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
3478+ }
33363479 }
33373480 used_variable_count = 0 ;
3481+ used_acessed_count = 0 ;
33383482 for (size_t i = 0 , j = 0 ; i < called_function_count ; ++ i ) {
33393483 while (p_parser -> functions [j ].id != p_called_functions [i ]) {
33403484 ++ j ;
@@ -3344,6 +3488,12 @@ static SpvReflectResult ParseStaticallyUsedResources(
33443488 p_parser -> functions [j ].accessed_ptrs ,
33453489 p_parser -> functions [j ].accessed_ptr_count * sizeof (* used_variables ));
33463490 used_variable_count += p_parser -> functions [j ].accessed_ptr_count ;
3491+
3492+ memcpy (& used_accesses [used_acessed_count ],
3493+ p_parser -> functions [j ].accessed_variable_ptrs ,
3494+ p_parser -> functions [j ].accessed_variable_ptr_count *
3495+ sizeof (SpvReflectPrvAccessedVariable ));
3496+ used_acessed_count += p_parser -> functions [j ].accessed_variable_ptr_count ;
33473497 }
33483498 SafeFree (p_called_functions );
33493499
@@ -3375,18 +3525,18 @@ static SpvReflectResult ParseStaticallyUsedResources(
33753525 & p_entry -> used_push_constants ,
33763526 & used_push_constant_count );
33773527
3378- for (uint32_t j = 0 ; j < p_module -> descriptor_binding_count ; ++ j ) {
3379- SpvReflectDescriptorBinding * p_binding = & p_module -> descriptor_bindings [j ];
3380- bool found = SearchSortedUint32 (
3381- used_variables ,
3382- used_variable_count ,
3383- p_binding -> spirv_id );
3384- if (found ) {
3385- p_binding -> accessed = 1 ;
3528+ for (uint32_t i = 0 ; i < p_module -> descriptor_binding_count ; ++ i ) {
3529+ SpvReflectDescriptorBinding * p_binding = & p_module -> descriptor_bindings [i ];
3530+ for (uint32_t j = 0 ; j < used_acessed_count ; j ++ ) {
3531+ if (used_accesses [j ].variable_ptr == p_binding -> spirv_id ) {
3532+ p_binding -> accessed = 1 ;
3533+ p_binding -> access_flags |= used_accesses [j ].access_flags ;
3534+ }
33863535 }
33873536 }
33883537
33893538 SafeFree (used_variables );
3539+ SafeFree (used_accesses );
33903540 if (result0 != SPV_REFLECT_RESULT_SUCCESS ) {
33913541 return result0 ;
33923542 }
0 commit comments