@@ -4,7 +4,10 @@ use std::{backtrace::Backtrace, fmt, sync::Arc};
44
55use log:: { debug, warn, Level } ;
66
7- use windows:: Win32 :: { Foundation :: E_OUTOFMEMORY , Graphics :: Direct3D12 :: * } ;
7+ use windows:: Win32 :: {
8+ Foundation :: E_OUTOFMEMORY ,
9+ Graphics :: { Direct3D12 :: * , Dxgi :: Common :: DXGI_FORMAT } ,
10+ } ;
811
912#[ cfg( feature = "public-winapi" ) ]
1013mod public_winapi {
@@ -110,6 +113,7 @@ pub struct ResourceCreateDesc<'a> {
110113 pub memory_location : MemoryLocation ,
111114 pub resource_category : ResourceCategory ,
112115 pub resource_desc : & ' a D3D12_RESOURCE_DESC ,
116+ pub castable_formats : & ' a [ DXGI_FORMAT ] ,
113117 pub clear_value : Option < & ' a D3D12_CLEAR_VALUE > ,
114118 pub initial_state_or_layout : ResourceStateOrBarrierLayout ,
115119 pub resource_type : & ' a ResourceType < ' a > ,
@@ -242,6 +246,8 @@ pub enum ID3D12DeviceVersion {
242246 /// Required for enhanced barrier support, i.e. when using
243247 /// [`ResourceStateOrBarrierLayout::BarrierLayout`].
244248 Device10 ( ID3D12Device10 ) ,
249+ /// Required for castable formats support, implies use of enhanced barriers
250+ Device12 ( ID3D12Device12 ) ,
245251}
246252
247253impl std:: ops:: Deref for ID3D12DeviceVersion {
@@ -250,8 +256,9 @@ impl std::ops::Deref for ID3D12DeviceVersion {
250256 fn deref ( & self ) -> & Self :: Target {
251257 match self {
252258 Self :: Device ( device) => device,
253- // Windows-rs hides CanInto, we know that Device10 is a subclass of Device but there's not even a Deref.
259+ // Windows-rs hides CanInto, we know that Device10/Device12 is a subclass of Device but there's not even a Deref.
254260 Self :: Device10 ( device10) => windows:: core:: CanInto :: can_into ( device10) ,
261+ Self :: Device12 ( device12) => windows:: core:: CanInto :: can_into ( device12) ,
255262 }
256263 }
257264}
@@ -806,6 +813,66 @@ impl Allocator {
806813 }
807814 }
808815
816+ fn d3d12_resource_desc_1 ( desc : & D3D12_RESOURCE_DESC ) -> D3D12_RESOURCE_DESC1 {
817+ D3D12_RESOURCE_DESC1 {
818+ Dimension : desc. Dimension ,
819+ Alignment : desc. Alignment ,
820+ Width : desc. Width ,
821+ Height : desc. Height ,
822+ DepthOrArraySize : desc. DepthOrArraySize ,
823+ MipLevels : desc. MipLevels ,
824+ Format : desc. Format ,
825+ SampleDesc : desc. SampleDesc ,
826+ Layout : desc. Layout ,
827+ Flags : desc. Flags ,
828+ // TODO: This is the only new field
829+ SamplerFeedbackMipRegion : D3D12_MIP_REGION :: default ( ) ,
830+ }
831+ }
832+
833+ fn resource_allocation_info (
834+ device : & ID3D12DeviceVersion ,
835+ desc : & ResourceCreateDesc < ' _ > ,
836+ ) -> D3D12_RESOURCE_ALLOCATION_INFO {
837+ match device {
838+ ID3D12DeviceVersion :: Device ( device) => unsafe {
839+ device. GetResourceAllocationInfo ( 0 , & [ * desc. resource_desc ] )
840+ } ,
841+ ID3D12DeviceVersion :: Device10 ( device) => unsafe {
842+ device. GetResourceAllocationInfo ( 0 , & [ * desc. resource_desc ] )
843+ } ,
844+ ID3D12DeviceVersion :: Device12 ( device) => unsafe {
845+ let resource_desc1 = Self :: d3d12_resource_desc_1 ( desc. resource_desc ) ;
846+
847+ let resource_descs = & [ resource_desc1] ;
848+
849+ // We always have one resource desc, hence we only have one mapping castable format array
850+ let num_castable_formats = desc. castable_formats . len ( ) as u32 ;
851+ let num_castable_formats_array = & [ num_castable_formats] ;
852+
853+ let castable_formats_array = & [ desc. castable_formats . as_ptr ( ) ] ;
854+
855+ let ( num_castable_formats_opt, castable_formats_opt) = if num_castable_formats > 0 {
856+ (
857+ Some ( num_castable_formats_array. as_ptr ( ) ) ,
858+ Some ( castable_formats_array. as_ptr ( ) ) ,
859+ )
860+ } else {
861+ ( None , None )
862+ } ;
863+
864+ device. GetResourceAllocationInfo3 (
865+ 0 ,
866+ resource_descs. len ( ) as u32 ,
867+ resource_descs. as_ptr ( ) ,
868+ num_castable_formats_opt,
869+ castable_formats_opt,
870+ None ,
871+ )
872+ } ,
873+ }
874+ }
875+
809876 /// Create a resource according to the provided parameters.
810877 /// Created resources should be freed at the end of their lifetime by calling [`Self::free_resource()`].
811878 pub fn create_resource ( & mut self , desc : & ResourceCreateDesc < ' _ > ) -> Result < Resource > {
@@ -821,34 +888,37 @@ impl Allocator {
821888
822889 if let Err ( e) = unsafe {
823890 match ( & self . device , desc. initial_state_or_layout ) {
824- ( device, ResourceStateOrBarrierLayout :: ResourceState ( initial_state) ) => {
825- device. CreateCommittedResource (
891+ ( _, ResourceStateOrBarrierLayout :: ResourceState ( _) )
892+ if !desc. castable_formats . is_empty ( ) =>
893+ {
894+ return Err ( AllocationError :: CastableFormatsRequiresEnhancedBarriers )
895+ }
896+ (
897+ ID3D12DeviceVersion :: Device12 ( device) ,
898+ ResourceStateOrBarrierLayout :: BarrierLayout ( initial_layout) ,
899+ ) => {
900+ let resource_desc1 = Self :: d3d12_resource_desc_1 ( desc. resource_desc ) ;
901+ device. CreateCommittedResource3 (
826902 * heap_properties,
827903 * heap_flags,
828- desc . resource_desc ,
829- initial_state ,
904+ & resource_desc1 ,
905+ initial_layout ,
830906 clear_value,
907+ None , // TODO
908+ Some ( desc. castable_formats ) ,
831909 & mut result,
832910 )
833911 }
912+ ( _, ResourceStateOrBarrierLayout :: BarrierLayout ( _) )
913+ if !desc. castable_formats . is_empty ( ) =>
914+ {
915+ return Err ( AllocationError :: CastableFormatsRequiresAtLeastDevice12 )
916+ }
834917 (
835918 ID3D12DeviceVersion :: Device10 ( device) ,
836919 ResourceStateOrBarrierLayout :: BarrierLayout ( initial_layout) ,
837920 ) => {
838- let resource_desc1 = D3D12_RESOURCE_DESC1 {
839- Dimension : desc. resource_desc . Dimension ,
840- Alignment : desc. resource_desc . Alignment ,
841- Width : desc. resource_desc . Width ,
842- Height : desc. resource_desc . Height ,
843- DepthOrArraySize : desc. resource_desc . DepthOrArraySize ,
844- MipLevels : desc. resource_desc . MipLevels ,
845- Format : desc. resource_desc . Format ,
846- SampleDesc : desc. resource_desc . SampleDesc ,
847- Layout : desc. resource_desc . Layout ,
848- Flags : desc. resource_desc . Flags ,
849- // TODO: This is the only new field
850- SamplerFeedbackMipRegion : D3D12_MIP_REGION :: default ( ) ,
851- } ;
921+ let resource_desc1 = Self :: d3d12_resource_desc_1 ( desc. resource_desc ) ;
852922
853923 device. CreateCommittedResource3 (
854924 * heap_properties,
@@ -857,11 +927,23 @@ impl Allocator {
857927 initial_layout,
858928 clear_value,
859929 None , // TODO
860- None , // TODO: https://github.com/microsoft/DirectX-Specs/blob/master/d3d/VulkanOn12.md#format-list-casting
930+ None ,
931+ & mut result,
932+ )
933+ }
934+ ( _, ResourceStateOrBarrierLayout :: BarrierLayout ( _) ) => {
935+ return Err ( AllocationError :: BarrierLayoutNeedsDevice10 )
936+ }
937+ ( device, ResourceStateOrBarrierLayout :: ResourceState ( initial_state) ) => {
938+ device. CreateCommittedResource (
939+ * heap_properties,
940+ * heap_flags,
941+ desc. resource_desc ,
942+ initial_state,
943+ clear_value,
861944 & mut result,
862945 )
863946 }
864- _ => return Err ( AllocationError :: BarrierLayoutNeedsDevice10 ) ,
865947 }
866948 } {
867949 return Err ( AllocationError :: Internal ( format ! (
@@ -872,10 +954,7 @@ impl Allocator {
872954
873955 let resource = result. expect ( "Allocation succeeded but no resource was returned?" ) ;
874956
875- let allocation_info = unsafe {
876- self . device
877- . GetResourceAllocationInfo ( 0 , & [ * desc. resource_desc ] )
878- } ;
957+ let allocation_info = Self :: resource_allocation_info ( & self . device , desc) ;
879958
880959 let memory_type = self
881960 . memory_types
@@ -906,10 +985,7 @@ impl Allocator {
906985 }
907986 ResourceType :: Placed => {
908987 let allocation_desc = {
909- let allocation_info = unsafe {
910- self . device
911- . GetResourceAllocationInfo ( 0 , & [ * desc. resource_desc ] )
912- } ;
988+ let allocation_info = Self :: resource_allocation_info ( & self . device , desc) ;
913989
914990 AllocationCreateDesc {
915991 name : desc. name ,
@@ -925,45 +1001,59 @@ impl Allocator {
9251001 let mut result: Option < ID3D12Resource > = None ;
9261002 if let Err ( e) = unsafe {
9271003 match ( & self . device , desc. initial_state_or_layout ) {
928- ( device, ResourceStateOrBarrierLayout :: ResourceState ( initial_state) ) => {
929- device. CreatePlacedResource (
1004+ ( _, ResourceStateOrBarrierLayout :: ResourceState ( _) )
1005+ if !desc. castable_formats . is_empty ( ) =>
1006+ {
1007+ return Err ( AllocationError :: CastableFormatsRequiresEnhancedBarriers )
1008+ }
1009+ (
1010+ ID3D12DeviceVersion :: Device12 ( device) ,
1011+ ResourceStateOrBarrierLayout :: BarrierLayout ( initial_layout) ,
1012+ ) => {
1013+ let resource_desc1 = Self :: d3d12_resource_desc_1 ( desc. resource_desc ) ;
1014+ device. CreatePlacedResource2 (
9301015 allocation. heap ( ) ,
9311016 allocation. offset ( ) ,
932- desc . resource_desc ,
933- initial_state ,
1017+ & resource_desc1 ,
1018+ initial_layout ,
9341019 None ,
1020+ Some ( desc. castable_formats ) ,
9351021 & mut result,
9361022 )
9371023 }
1024+ ( _, ResourceStateOrBarrierLayout :: BarrierLayout ( _) )
1025+ if !desc. castable_formats . is_empty ( ) =>
1026+ {
1027+ return Err ( AllocationError :: CastableFormatsRequiresAtLeastDevice12 )
1028+ }
9381029 (
9391030 ID3D12DeviceVersion :: Device10 ( device) ,
9401031 ResourceStateOrBarrierLayout :: BarrierLayout ( initial_layout) ,
9411032 ) => {
942- let resource_desc1 = D3D12_RESOURCE_DESC1 {
943- Dimension : desc. resource_desc . Dimension ,
944- Alignment : desc. resource_desc . Alignment ,
945- Width : desc. resource_desc . Width ,
946- Height : desc. resource_desc . Height ,
947- DepthOrArraySize : desc. resource_desc . DepthOrArraySize ,
948- MipLevels : desc. resource_desc . MipLevels ,
949- Format : desc. resource_desc . Format ,
950- SampleDesc : desc. resource_desc . SampleDesc ,
951- Layout : desc. resource_desc . Layout ,
952- Flags : desc. resource_desc . Flags ,
953- // TODO: This is the only new field
954- SamplerFeedbackMipRegion : D3D12_MIP_REGION :: default ( ) ,
955- } ;
1033+ let resource_desc1 = Self :: d3d12_resource_desc_1 ( desc. resource_desc ) ;
9561034 device. CreatePlacedResource2 (
9571035 allocation. heap ( ) ,
9581036 allocation. offset ( ) ,
9591037 & resource_desc1,
9601038 initial_layout,
9611039 None ,
962- None , // TODO: https://github.com/microsoft/DirectX-Specs/blob/master/d3d/VulkanOn12.md#format-list-casting
1040+ None ,
1041+ & mut result,
1042+ )
1043+ }
1044+ ( _, ResourceStateOrBarrierLayout :: BarrierLayout ( _) ) => {
1045+ return Err ( AllocationError :: BarrierLayoutNeedsDevice10 )
1046+ }
1047+ ( device, ResourceStateOrBarrierLayout :: ResourceState ( initial_state) ) => {
1048+ device. CreatePlacedResource (
1049+ allocation. heap ( ) ,
1050+ allocation. offset ( ) ,
1051+ desc. resource_desc ,
1052+ initial_state,
1053+ None ,
9631054 & mut result,
9641055 )
9651056 }
966- _ => return Err ( AllocationError :: BarrierLayoutNeedsDevice10 ) ,
9671057 }
9681058 } {
9691059 return Err ( AllocationError :: Internal ( format ! (
0 commit comments