Jump to content
  • Advertisement
Sign in to follow this  
Funkymunky

[D3D12] Mapping a Resource to an address

This topic is 1026 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Right now I call ID3D12Resource::Map to get a location to copy memory to when updating a cbuffer.  Reading Hodgman's reply to this post, he mentions:

 

 

 

When the high level code asks to bind a cbuffer, I memcpy it's contents (from my own malloc'ed RAM) into my D3D12 stack, and then give that stack pointer to d3d as the cbuffer address.

 

This is the part I'm confused about.  How are you able to tell D3D12 where to look for the cbuffer data at?  It seems like calling Map gives you a pointer to use, where the driver has allocated that memory.

Share this post


Link to post
Share on other sites
Advertisement

That does look like the job of the D3D12_CPU_DESCRIPTOR_HANDLE that you pass to CreateConstantBufferView.  Is he really suggesting calling CreateConstantBufferView for each binding of a cbuffer?  And plus, when I call that function, I pass it the result of ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart(), not a memory address...

Share this post


Link to post
Share on other sites

Those are recommended to be used "only sparingly", and I don't think they let you specify the address of where the buffer gets mapped to on the CPU side anyway.

Share this post


Link to post
Share on other sites


Those are recommended to be used "only sparingly"

Isn't that because there size, in relation to the smallness of the root signature?

 


and I don't think they let you specify the address of where the buffer gets mapped to on the CPU side anyway.



Quote
 
 
When the high level code asks to bind a cbuffer, I memcpy it's contents (from my own malloc'ed RAM) into my D3D12 stack, and then give that stack pointer to d3d as the cbuffer address.
 

According to your quote he puts the data from CPU malloc'd RAM onto his "D3D12 stack" and then gives that gpu memory pointer as the cbuffer address.

 

Or am I misunderstanding your point?

Share this post


Link to post
Share on other sites

I don't think when he says he's putting the malloc'd RAM into his D3D12 stack that he means he's using a cbuffer inside the root signature.

Share this post


Link to post
Share on other sites


That does look like the job of the D3D12_CPU_DESCRIPTOR_HANDLE that you pass to CreateConstantBufferView.

BTW I wasn't referring to that I was referring to "cbvDesc.BufferLocation" which is the GPU virtual address of the resource in question for the view.

 


I don't think when he says he's putting the malloc'd RAM into his D3D12 stack that he means he's using a cbuffer inside the root signature.

I'm not saying the Cbuffer is in the root signature... I'm saying the Cbuffer descriptor could be put in the root signature.

 

Well hopefully Hodgman will grace us with his presence.

Share this post


Link to post
Share on other sites


How are you able to tell D3D12 where to look for the cbuffer data at?  It seems like calling Map gives you a pointer to use, where the driver has allocated that memory.


That does look like the job of the D3D12_CPU_DESCRIPTOR_HANDLE that you pass to CreateConstantBufferView.  Is he really suggesting calling CreateConstantBufferView for each binding of a cbuffer?  And plus, when I call that function, I pass it the result of ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart(), not a memory address...
Yeah you put a memory address into a D3D12_CONSTANT_BUFFER_VIEW_DESC, and then D3D copies that into a descriptor for you. When you want to tell D3D to read constants from your memory address, you give it this descriptor. So, "giving a pointer to d3d" == "giving it a descriptor that contains this pointer".

 

 

You can try calling CreateConstantBufferView on every bind, it probably actually won't be too bad :) I pretty much do that on consoles, but you're in control of memory management there a lot more, so I can actually get away with doing this without causing any allocations to actually occur (just patching some data in-place...).

 

What you can do on PC to avoid these allocations is pre-create a whole bunch of descriptors (cbuffer-views) for each 256 byte block of your huge buffer. e.g.

* Create a big buffer (your 'constant stack'), large enough to hold every dynamic constant required in your frame, plus padding... Unfortunately D3D12 mandates that buffers be 256byte aligned.

* Get the base address of the buffer and in a loop that increments this address by 256 bytes, pre-create cbuffer-views/descriptors for each 256 byte block.

* Repeat that loop with different sizes if required (e.g. for 1KB buffers, or 4KB buffers).

* Now when the user needs to supply dynamic constants, write them into your giant buffer at the appropriate offset, and then fetch the pre-created view/desecriptor that corresponds with this offset.

* Give that descriptor to D3D as your cbuffer data.

 

Next frame, switch to using a different constant-stack buffer. The frame after that, use a fence to ensure the GPU has finished with the previous-previous frame, and then reuse the first constant-stack buffer again.

 

For non-dynamic cbuffers, don't bother with any of this and just pre-allocate their immutable data, and pre-create their descriptor.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!