Sign in to follow this  

[D3D12] Mapping a Resource to an address

This topic is 808 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

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

If I'm not mistaken you can put a CBV directly in the Root Signature.

 

edit - https://msdn.microsoft.com/en-us/library/windows/desktop/dn899223(v=vs.85).aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/dn903911(v=vs.85).aspx

Edited by Infinisearch

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


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

This topic is 808 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this