@@ -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
@@ -691,6 +709,7 @@ static void DestroyParser(SpvReflectPrvParser* p_parser)
691709 SafeFree (p_parser -> functions [i ].callees );
692710 SafeFree (p_parser -> functions [i ].callee_ptrs );
693711 SafeFree (p_parser -> functions [i ].accessed_ptrs );
712+ SafeFree (p_parser -> functions [i ].accessed_variable_ptrs );
694713 }
695714
696715 // Free access chains
@@ -1166,6 +1185,7 @@ static SpvReflectResult ParseFunction(
11661185 p_func -> callee_count = 0 ;
11671186 p_func -> accessed_ptr_count = 0 ;
11681187
1188+ // First get count to know how much to allocate
11691189 for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
11701190 SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
11711191 if (p_node -> op == SpvOpFunctionEnd ) {
@@ -1213,10 +1233,17 @@ static SpvReflectResult ParseFunction(
12131233 if (IsNull (p_func -> accessed_ptrs )) {
12141234 return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
12151235 }
1236+
1237+ p_func -> accessed_variable_ptrs = (SpvReflectPrvAccessedVariable * )calloc (
1238+ p_func -> accessed_ptr_count , sizeof (* (p_func -> accessed_variable_ptrs )));
1239+ if (IsNull (p_func -> accessed_variable_ptrs )) {
1240+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
1241+ }
12161242 }
12171243
12181244 p_func -> callee_count = 0 ;
12191245 p_func -> accessed_ptr_count = 0 ;
1246+ // Now have allocation, fill in values
12201247 for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
12211248 SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
12221249 if (p_node -> op == SpvOpFunctionEnd ) {
@@ -1227,26 +1254,74 @@ static SpvReflectResult ParseFunction(
12271254 CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
12281255 p_func -> callees [p_func -> callee_count ]);
12291256 (++ p_func -> callee_count );
1230- }
1231- break ;
1232- case SpvOpLoad :
1257+ } break ;
12331258 case SpvOpAccessChain :
12341259 case SpvOpInBoundsAccessChain :
12351260 case SpvOpPtrAccessChain :
12361261 case SpvOpArrayLength :
12371262 case SpvOpGenericPtrMemSemantics :
1238- case SpvOpInBoundsPtrAccessChain :
1263+ case SpvOpInBoundsPtrAccessChain : {
1264+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
1265+ p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1266+
1267+ CHECKED_READU32 (
1268+ p_parser , p_node -> word_offset + 3 ,
1269+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1270+ .variable_ptr );
1271+ // Need to track Result ID as not sure there has been any memory access
1272+ // through here yet
1273+ CHECKED_READU32 (
1274+ p_parser , p_node -> word_offset + 2 ,
1275+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1276+ .result_id );
1277+ (++ p_func -> accessed_ptr_count );
1278+ } break ;
1279+ case SpvOpLoad : {
1280+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
1281+ p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1282+
1283+ CHECKED_READU32 (
1284+ p_parser , p_node -> word_offset + 3 ,
1285+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1286+ .variable_ptr );
1287+ CHECKED_READU32 (
1288+ p_parser , p_node -> word_offset + 2 ,
1289+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1290+ .result_id );
1291+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1292+ .access_flags = SPV_REFLECT_ACCESS_READ ;
1293+ (++ p_func -> accessed_ptr_count );
1294+ } break ;
12391295 case SpvOpImageTexelPointer :
12401296 {
12411297 CHECKED_READU32 (p_parser , p_node -> word_offset + 3 ,
12421298 p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1299+
1300+ CHECKED_READU32 (
1301+ p_parser , p_node -> word_offset + 3 ,
1302+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1303+ .variable_ptr );
1304+ CHECKED_READU32 (
1305+ p_parser , p_node -> word_offset + 2 ,
1306+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1307+ .result_id );
1308+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1309+ .access_flags = SPV_REFLECT_ACCESS_ATOMIC |
1310+ SPV_REFLECT_ACCESS_READ | SPV_REFLECT_ACCESS_WRITE ;
12431311 (++ p_func -> accessed_ptr_count );
12441312 }
12451313 break ;
12461314 case SpvOpStore :
12471315 {
12481316 CHECKED_READU32 (p_parser , p_node -> word_offset + 2 ,
12491317 p_func -> accessed_ptrs [p_func -> accessed_ptr_count ]);
1318+
1319+ CHECKED_READU32 (
1320+ p_parser , p_node -> word_offset + 2 ,
1321+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1322+ .variable_ptr );
1323+ p_func -> accessed_variable_ptrs [p_func -> accessed_ptr_count ]
1324+ .access_flags = SPV_REFLECT_ACCESS_WRITE ;
12501325 (++ p_func -> accessed_ptr_count );
12511326 }
12521327 break ;
@@ -1265,6 +1340,66 @@ static SpvReflectResult ParseFunction(
12651340 }
12661341 }
12671342
1343+ // Apply the SpvReflectAccessFlags to all things touching an OpVariable
1344+ for (size_t i = first_label_index ; i < p_parser -> node_count ; ++ i ) {
1345+ SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
1346+ if (p_node -> op == SpvOpFunctionEnd ) {
1347+ break ;
1348+ }
1349+ // These are memory accesses instruction
1350+ uint32_t memory_access_ptr = 0 ;
1351+ SpvReflectAccessFlags memory_access_type = SPV_REFLECT_ACCESS_NONE ;
1352+ switch (p_node -> op ) {
1353+ case SpvOpLoad : {
1354+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , memory_access_ptr );
1355+ memory_access_type = SPV_REFLECT_ACCESS_READ ;
1356+ } break ;
1357+ case SpvOpImageWrite :
1358+ case SpvOpStore : {
1359+ CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , memory_access_ptr );
1360+ memory_access_type = SPV_REFLECT_ACCESS_WRITE ;
1361+ } break ;
1362+ case SpvOpImageTexelPointer :
1363+ case SpvOpAtomicLoad :
1364+ case SpvOpAtomicExchange :
1365+ case SpvOpAtomicCompareExchange :
1366+ case SpvOpAtomicIIncrement :
1367+ case SpvOpAtomicIDecrement :
1368+ case SpvOpAtomicIAdd :
1369+ case SpvOpAtomicISub :
1370+ case SpvOpAtomicSMin :
1371+ case SpvOpAtomicUMin :
1372+ case SpvOpAtomicSMax :
1373+ case SpvOpAtomicUMax :
1374+ case SpvOpAtomicAnd :
1375+ case SpvOpAtomicOr :
1376+ case SpvOpAtomicXor :
1377+ case SpvOpAtomicFMinEXT :
1378+ case SpvOpAtomicFMaxEXT :
1379+ case SpvOpAtomicFAddEXT : {
1380+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , memory_access_ptr );
1381+ memory_access_type = SPV_REFLECT_ACCESS_ATOMIC |
1382+ SPV_REFLECT_ACCESS_READ | SPV_REFLECT_ACCESS_WRITE ;
1383+ } break ;
1384+ case SpvOpAtomicStore : {
1385+ CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , memory_access_ptr );
1386+ memory_access_type = SPV_REFLECT_ACCESS_ATOMIC |
1387+ SPV_REFLECT_ACCESS_READ | SPV_REFLECT_ACCESS_WRITE ;
1388+ } break ;
1389+ default :
1390+ break ;
1391+ }
1392+
1393+ if (memory_access_ptr == 0 ) {
1394+ continue ;
1395+ }
1396+ for (uint32_t k = 0 ; k < p_func -> accessed_ptr_count ; k ++ ) {
1397+ if (p_func -> accessed_variable_ptrs [k ].result_id == memory_access_ptr ) {
1398+ p_func -> accessed_variable_ptrs [k ].access_flags |= memory_access_type ;
1399+ }
1400+ }
1401+ }
1402+
12681403 if (p_func -> callee_count > 0 ) {
12691404 qsort (p_func -> callees , p_func -> callee_count ,
12701405 sizeof (* (p_func -> callees )), SortCompareUint32 );
@@ -1276,6 +1411,7 @@ static SpvReflectResult ParseFunction(
12761411 qsort (p_func -> accessed_ptrs , p_func -> accessed_ptr_count ,
12771412 sizeof (* (p_func -> accessed_ptrs )), SortCompareUint32 );
12781413 }
1414+ p_func -> accessed_variable_ptr_count = p_func -> accessed_ptr_count ;
12791415 p_func -> accessed_ptr_count = (uint32_t )DedupSortedUint32 (p_func -> accessed_ptrs ,
12801416 p_func -> accessed_ptr_count );
12811417
@@ -3323,24 +3459,35 @@ static SpvReflectResult ParseStaticallyUsedResources(
33233459 called_function_count = DedupSortedUint32 (p_called_functions , called_function_count );
33243460
33253461 uint32_t used_variable_count = 0 ;
3462+ uint32_t used_acessed_count = 0 ;
33263463 for (size_t i = 0 , j = 0 ; i < called_function_count ; ++ i ) {
33273464 // No need to bounds check j because a missing ID issue would have been
33283465 // found during TraverseCallGraph
33293466 while (p_parser -> functions [j ].id != p_called_functions [i ]) {
33303467 ++ j ;
33313468 }
33323469 used_variable_count += p_parser -> functions [j ].accessed_ptr_count ;
3470+ used_acessed_count += p_parser -> functions [j ].accessed_variable_ptr_count ;
33333471 }
33343472 uint32_t * used_variables = NULL ;
3473+ SpvReflectPrvAccessedVariable * used_accesses = NULL ;
33353474 if (used_variable_count > 0 ) {
33363475 used_variables = (uint32_t * )calloc (used_variable_count ,
33373476 sizeof (* used_variables ));
33383477 if (IsNull (used_variables )) {
33393478 SafeFree (p_called_functions );
33403479 return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
33413480 }
3481+
3482+ used_accesses = (SpvReflectPrvAccessedVariable * )calloc (
3483+ used_acessed_count , sizeof (SpvReflectPrvAccessedVariable ));
3484+ if (IsNull (used_accesses )) {
3485+ SafeFree (p_called_functions );
3486+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
3487+ }
33423488 }
33433489 used_variable_count = 0 ;
3490+ used_acessed_count = 0 ;
33443491 for (size_t i = 0 , j = 0 ; i < called_function_count ; ++ i ) {
33453492 while (p_parser -> functions [j ].id != p_called_functions [i ]) {
33463493 ++ j ;
@@ -3350,6 +3497,12 @@ static SpvReflectResult ParseStaticallyUsedResources(
33503497 p_parser -> functions [j ].accessed_ptrs ,
33513498 p_parser -> functions [j ].accessed_ptr_count * sizeof (* used_variables ));
33523499 used_variable_count += p_parser -> functions [j ].accessed_ptr_count ;
3500+
3501+ memcpy (& used_accesses [used_acessed_count ],
3502+ p_parser -> functions [j ].accessed_variable_ptrs ,
3503+ p_parser -> functions [j ].accessed_variable_ptr_count *
3504+ sizeof (SpvReflectPrvAccessedVariable ));
3505+ used_acessed_count += p_parser -> functions [j ].accessed_variable_ptr_count ;
33533506 }
33543507 SafeFree (p_called_functions );
33553508
@@ -3381,18 +3534,18 @@ static SpvReflectResult ParseStaticallyUsedResources(
33813534 & p_entry -> used_push_constants ,
33823535 & used_push_constant_count );
33833536
3384- for (uint32_t j = 0 ; j < p_module -> descriptor_binding_count ; ++ j ) {
3385- SpvReflectDescriptorBinding * p_binding = & p_module -> descriptor_bindings [j ];
3386- bool found = SearchSortedUint32 (
3387- used_variables ,
3388- used_variable_count ,
3389- p_binding -> spirv_id );
3390- if (found ) {
3391- p_binding -> accessed = 1 ;
3537+ for (uint32_t i = 0 ; i < p_module -> descriptor_binding_count ; ++ i ) {
3538+ SpvReflectDescriptorBinding * p_binding = & p_module -> descriptor_bindings [i ];
3539+ for (uint32_t j = 0 ; j < used_acessed_count ; j ++ ) {
3540+ if (used_accesses [j ].variable_ptr == p_binding -> spirv_id ) {
3541+ p_binding -> accessed = 1 ;
3542+ p_binding -> access_flags |= used_accesses [j ].access_flags ;
3543+ }
33923544 }
33933545 }
33943546
33953547 SafeFree (used_variables );
3548+ SafeFree (used_accesses );
33963549 if (result0 != SPV_REFLECT_RESULT_SUCCESS ) {
33973550 return result0 ;
33983551 }
0 commit comments