1
1
// =============================================================================
2
- // Copyright (c) 2019-2021 Advanced Micro Devices, Inc. All rights reserved.
2
+ // Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
3
3
// / @author AMD Developer Tools Team
4
4
// / @file
5
5
// / @brief Implementation of functions for working with a data set.
6
6
// =============================================================================
7
7
8
8
#include < map>
9
- #include < set >
9
+ #include < unordered_set >
10
10
#include < stdlib.h> // for malloc() / free()
11
11
#include < string>
12
12
#include < string.h> // for memcpy()
@@ -102,7 +102,10 @@ static std::map<RmtCorrelationIdentifier, RmtResourceNameData> resource_name_loo
102
102
static std::map<RmtResourceIdentifier, RmtResourceIdentifier> unique_resource_id_lookup_map;
103
103
104
104
// A list of implicit resources to be removed from a snapshot.
105
- static std::set<RmtResourceIdentifier> implicit_resource_list;
105
+ static std::unordered_set<RmtResourceIdentifier> implicit_resource_list;
106
+
107
+ // The set of created resources at any point in time.
108
+ static std::unordered_set<RmtResourceIdentifier> created_resources;
106
109
107
110
// A flag used to indicate that the list of implicit resources has been created.
108
111
// This list is created when the trace is first parsed and the timeline is built.
@@ -407,6 +410,22 @@ static RmtErrorCode ParseChunks(RmtDataSet* data_set)
407
410
return kRmtOk ;
408
411
}
409
412
413
+ // Check for SAM (Smart access memory) support.
414
+ //
415
+ // Without SAM support, the local memory size is 256MB. If SAM is enabled, the local memory
416
+ // will be the total GPU memory. In addition, the invisible memory available will be 0 bytes.
417
+ static void CheckForSAMSupport (RmtDataSet* data_set)
418
+ {
419
+ if (data_set->segment_info [kRmtHeapTypeInvisible ].size == 0 )
420
+ {
421
+ data_set->sam_enabled = true ;
422
+ }
423
+ else
424
+ {
425
+ data_set->sam_enabled = false ;
426
+ }
427
+ }
428
+
410
429
static void BuildDataProfileParseUserdata (RmtDataSet* data_set, const RmtToken* current_token)
411
430
{
412
431
RMT_ASSERT (current_token->type == kRmtTokenTypeUserdata );
@@ -459,10 +478,13 @@ static void BuildDataProfileParseResourceCreate(RmtDataSet* data_set, const RmtT
459
478
{
460
479
RMT_ASSERT (current_token->type == kRmtTokenTypeResourceCreate );
461
480
481
+ // Add this resource to the list of created resources, and keep track of the maximum number of concurrent resources.
482
+ created_resources.insert (current_token->resource_create_token .resource_identifier );
483
+ data_set->data_profile .max_concurrent_resources =
484
+ RMT_MAXIMUM (data_set->data_profile .max_concurrent_resources , static_cast <int32_t >(created_resources.size ()));
485
+
462
486
data_set->data_profile .current_resource_count ++;
463
487
data_set->data_profile .total_resource_count ++;
464
- data_set->data_profile .max_concurrent_resources =
465
- RMT_MAXIMUM (data_set->data_profile .max_concurrent_resources , data_set->data_profile .current_resource_count );
466
488
467
489
// Add one to the allocation count if the resource being created is a shareable image, since we might need to create a dummy allocation token
468
490
// if we don't see one in the token stream.
@@ -480,6 +502,11 @@ static void BuildDataProfileParseResourceDestroy(RmtDataSet* data_set, const Rmt
480
502
{
481
503
RMT_ASSERT (current_token->type == kRmtTokenTypeResourceDestroy );
482
504
505
+ // Only remove the resource from list of created resources if it has previously been created.
506
+ if (created_resources.find (current_token->resource_create_token .resource_identifier ) != created_resources.end ())
507
+ {
508
+ created_resources.erase (current_token->resource_create_token .resource_identifier );
509
+ }
483
510
data_set->data_profile .current_resource_count --;
484
511
}
485
512
@@ -499,6 +526,8 @@ static RmtErrorCode BuildDataProfile(RmtDataSet* data_set)
499
526
RmtProcessMapAddProcess (&data_set->process_map , data_set->process_start_info [current_process_start_index].process_id );
500
527
}
501
528
529
+ created_resources.clear ();
530
+
502
531
// if the heap has something there, then add it.
503
532
while (!RmtStreamMergerIsEmpty (&data_set->stream_merger ))
504
533
{
@@ -542,6 +571,8 @@ static RmtErrorCode BuildDataProfile(RmtDataSet* data_set)
542
571
}
543
572
}
544
573
574
+ created_resources.clear ();
575
+
545
576
data_set->cpu_frequency = data_set->streams [0 ].cpu_frequency ;
546
577
547
578
// Create an allocator for the token heap to use for generating unique resource IDs
@@ -587,7 +618,7 @@ static RmtErrorCode AllocateMemoryForSnapshot(RmtDataSet* data_set, RmtDataSnaps
587
618
588
619
// Initialize the virtual allocation list.
589
620
const size_t virtual_allocation_buffer_size =
590
- RmtVirtualAllocationListGetBufferSize (data_set->data_profile .total_virtual_allocation_count , data_set->data_profile .max_concurrent_resources + 200 );
621
+ RmtVirtualAllocationListGetBufferSize (data_set->data_profile .total_virtual_allocation_count , data_set->data_profile .max_concurrent_resources );
591
622
if (virtual_allocation_buffer_size > 0 )
592
623
{
593
624
out_snapshot->virtual_allocation_buffer = PerformAllocation (data_set, virtual_allocation_buffer_size, sizeof (uint32_t ));
@@ -597,14 +628,14 @@ static RmtErrorCode AllocateMemoryForSnapshot(RmtDataSet* data_set, RmtDataSnaps
597
628
out_snapshot->virtual_allocation_buffer ,
598
629
virtual_allocation_buffer_size,
599
630
data_set->data_profile .max_virtual_allocation_count ,
600
- data_set->data_profile .max_concurrent_resources + 200 ,
631
+ data_set->data_profile .max_concurrent_resources ,
601
632
data_set->data_profile .total_virtual_allocation_count );
602
633
RMT_ASSERT (error_code == kRmtOk );
603
634
RMT_RETURN_ON_ERROR (error_code == kRmtOk , error_code);
604
635
}
605
636
606
637
// create the resource list.
607
- const size_t resource_list_buffer_size = RmtResourceListGetBufferSize (data_set->data_profile .max_concurrent_resources + 200 );
638
+ const size_t resource_list_buffer_size = RmtResourceListGetBufferSize (data_set->data_profile .max_concurrent_resources );
608
639
if (resource_list_buffer_size > 0 )
609
640
{
610
641
out_snapshot->resource_list_buffer = PerformAllocation (data_set, resource_list_buffer_size, sizeof (uint32_t ));
@@ -614,7 +645,7 @@ static RmtErrorCode AllocateMemoryForSnapshot(RmtDataSet* data_set, RmtDataSnaps
614
645
out_snapshot->resource_list_buffer ,
615
646
resource_list_buffer_size,
616
647
&out_snapshot->virtual_allocation_list ,
617
- data_set->data_profile .max_concurrent_resources + 200 );
648
+ data_set->data_profile .max_concurrent_resources );
618
649
RMT_ASSERT (error_code == kRmtOk );
619
650
RMT_RETURN_ON_ERROR (error_code == kRmtOk , error_code);
620
651
}
@@ -793,12 +824,15 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr
793
824
current_token->resource_bind_token .virtual_address ,
794
825
(int32_t )(current_token->resource_bind_token .size_in_bytes >> 12 ),
795
826
kDummyHeapPref ,
796
- RmtOwnerType::kRmtOwnerTypeClientDriver );
827
+ RmtOwnerType::kRmtOwnerTypeClientDriver ,
828
+ data_set->sam_enabled );
797
829
}
798
830
else if (error_code == kRmtErrorResourceAlreadyBound )
799
831
{
800
- // duplicate the command allocator resource we have at this resource ID this is because command allocators are
801
- // bound to multiple chunks of virtual address space simultaneously.
832
+ // Handle the case where the resource is already bound to a virtual memory allocation.
833
+ // This can occur for command allocators which can be bound to multiple chunks of virtual
834
+ // address space simultaneously or buffer resources already bound to an allocation. These
835
+ // resources are implicitly destroyed, created again and bound to a different allocation.
802
836
const RmtResource* matching_resource = NULL ;
803
837
error_code = RmtResourceListGetResourceByResourceId (
804
838
&out_snapshot->resource_list , current_token->resource_bind_token .resource_identifier , &matching_resource);
@@ -809,24 +843,40 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr
809
843
resource_create_token.resource_identifier = matching_resource->identifier ;
810
844
resource_create_token.owner_type = matching_resource->owner_type ;
811
845
resource_create_token.commit_type = matching_resource->commit_type ;
812
- resource_create_token.resource_type = kRmtResourceTypeCommandAllocator ;
846
+ resource_create_token.resource_type = matching_resource-> resource_type ;
813
847
memcpy (&resource_create_token.common , ¤t_token->common , sizeof (RmtTokenCommon));
814
- memcpy (&resource_create_token.command_allocator , &matching_resource->command_allocator , sizeof (RmtResourceDescriptionCommandAllocator));
815
848
816
- // Create the resource.
849
+ switch (matching_resource->resource_type )
850
+ {
851
+ case kRmtResourceTypeCommandAllocator :
852
+ memcpy (&resource_create_token.command_allocator , &matching_resource->command_allocator , sizeof (RmtResourceDescriptionCommandAllocator));
853
+ break ;
854
+
855
+ case kRmtResourceTypeBuffer :
856
+ memcpy (&resource_create_token.buffer , &matching_resource->buffer , sizeof (RmtResourceDescriptionBuffer));
857
+ break ;
858
+
859
+ default :
860
+ // Unexpected resource type.
861
+ RMT_ASSERT_FAIL (" Re-binding is only supported for buffer and command allocator resource types" );
862
+ break ;
863
+ }
864
+
865
+ // Create the resource. Since the resource already exists, the Create operation will implicitly destroy it first.
817
866
error_code = RmtResourceListAddResourceCreate (&out_snapshot->resource_list , &resource_create_token);
818
867
RMT_ASSERT (error_code == kRmtOk );
819
868
820
869
if (!(current_token->resource_bind_token .is_system_memory && current_token->resource_bind_token .virtual_address == 0 ))
821
870
{
871
+ // Re-bind the resource to its new virtual memory allocation.
822
872
error_code = RmtResourceListAddResourceBind (&out_snapshot->resource_list , ¤t_token->resource_bind_token );
823
873
RMT_ASSERT (error_code == kRmtOk );
824
874
}
825
875
}
826
876
}
827
877
828
878
RMT_ASSERT (error_code == kRmtOk );
829
- // RMT_RETURN_ON_ERROR(error_code == kRmtOk, error_code);
879
+ // RMT_RETURN_ON_ERROR(error_code == kRmtOk, error_code);
830
880
}
831
881
break ;
832
882
@@ -877,13 +927,13 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr
877
927
current_token->virtual_allocate_token .virtual_address ,
878
928
current_token->virtual_allocate_token .size_in_bytes );
879
929
#endif
880
-
881
930
error_code = RmtVirtualAllocationListAddAllocation (&out_snapshot->virtual_allocation_list ,
882
931
current_token->common .timestamp ,
883
932
current_token->virtual_allocate_token .virtual_address ,
884
933
(int32_t )(current_token->virtual_allocate_token .size_in_bytes >> 12 ),
885
934
current_token->virtual_allocate_token .preference ,
886
- current_token->virtual_allocate_token .owner_type );
935
+ current_token->virtual_allocate_token .owner_type ,
936
+ data_set->sam_enabled );
887
937
RMT_ASSERT (error_code == kRmtOk );
888
938
RMT_RETURN_ON_ERROR (error_code == kRmtOk , error_code);
889
939
}
@@ -1064,6 +1114,8 @@ RmtErrorCode RmtDataSetInitialize(const char* path, RmtDataSet* data_set)
1064
1114
RMT_ASSERT (error_code == kRmtOk );
1065
1115
RMT_RETURN_ON_ERROR (error_code == kRmtOk , error_code);
1066
1116
1117
+ CheckForSAMSupport (data_set);
1118
+
1067
1119
// construct the data profile for subsequent data parsing.
1068
1120
error_code = BuildDataProfile (data_set);
1069
1121
RMT_ASSERT (error_code == kRmtOk );
0 commit comments