• Advertisement
Sign in to follow this  

DX11 [DX11]UpdateSubresource-What am I missing?

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

Im trying to change the mesh of a vertex buffer using UpdateSubresource, the layout is the same, everything is the same, I just trying to change the vertices(from a ball to a cube, lets say). Since everything is the same I though doing just a call to UpdateSubresource and then IASetVertexBuffers would be fine, but notting happens, the ball is still being rendered...So Im probaly missing some concepts..No warnings or errors are being displayed on the output.. Some code: The buffer I create at first, this works fine:
D3D11_BUFFER_DESC buffdesc = {0};
		buffdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		buffdesc.ByteWidth = iSizeOfpV_p;//sizeof( vposnormaltex )*24;//
		buffdesc.Usage = D3D11_USAGE_DEFAULT;
		D3D11_SUBRESOURCE_DATA subres = {0};
			subres.pSysMem = pV_p;//vertex array(ball)


	if( pDevice_p->CreateBuffer( &buffdesc, &subres, &pVBuff_p ) != S_OK ) return E_FAIL;

So I create the Input Layout to the input assemble stage, this works fine also.
//Create Input Layout(based on the desc passed as param)
	D3DX11_PASS_DESC passdesc = {0};
		pEPass_p->GetDesc( &passdesc );

	donne( pInputLayout_p );

	if( pDevice_p->CreateInputLayout(	InputElmDesc_p, NumElm,
										passdesc.pIAInputSignature, passdesc.IAInputSignatureSize,
										&pInputLayout_p ) != S_OK ){
		
		for( UINT i=0; i<NumVB; i++ ) donne( pVBuff_p[i] );
		for( UINT i=0; i<NumIB; i++ ) donne( pIBuff_p[i] );

		return E_FAIL;
	}


	//bind buffers(vertex mesh) to the IA:
	UINT offset = NULL;
	pDIContext_p->IASetVertexBuffers( 0, NumVB, pVBuff_p, strides, &offset );


	//set the input layout to the Input Assembly
	pDIContext_p->IASetInputLayout( pInputLayout_p );

	//set primitive type:
	pDIContext_p->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
Now Im trying to just update the vertex buffer, so I can display other stuff, Im doing this:
//Update VBuffer with new data:
	D3D11_BOX bla; ZeroMemory( &bla, sizeof(D3D11_BOX));
	pDIContext_p->UpdateSubresource( pVBuff_p, 0, &bla, pV_p, 0, 0 );


	//Bind VBuffer to the Input Assemble
	UINT offset = NULL;	
	pDIContext_p->IASetVertexBuffers( 0, 1, &pVBuff_p, &strides[0], &offset );
pVBuff is the same vertex buffer used for the ball, its not Resource interface, is a Buffer interface.. Like I said, nothing happens..What Is going on?

Share this post


Link to post
Share on other sites
Advertisement
Please run this in a debugger with a debug device and then step through the code call to UpdateSubResource() and see what debug messages occur. That should tell us what the problem is.

And, your D3D10_BOX is all zeros, which should mean copy nothing. To copy the entire contents you should pass in NULL for the box.

Share this post


Link to post
Share on other sites
Quote:
Original post by DieterVW
Please run this in a debugger with a debug device and then step through the code call to UpdateSubResource() and see what debug messages occur. That should tell us what the problem is.

And, your D3D10_BOX is all zeros, which should mean copy nothing. To copy the entire contents you should pass in NULL for the box.


1- Im alredy runing with a debug device.
2- Null for D3D11_BOX results on access violation
Should I set this box with 1 ? Just tryied that, nothing happens yet.
-edit-
Just checked the sdk for the box:
A box that defines the portion of the destination subresource to copy the resource data into. Coordinates are in bytes for buffers and in texels for textures. If NULL, the data is written to the destination subresource with no offset. The dimensions of the source must fit the destination.

So why Im getting access violation when passing NULL? Because my cube have less vertices than the ball? How should I set this cube?

Share this post


Link to post
Share on other sites
Maybe the D3D debug layer has a bug. Try running without the debug layer and see if null works then.

Share this post


Link to post
Share on other sites
Very weird, I tested a bunch of times, some times it works, sometimes dont,most times dont, but when it works, it works ALWAYS when I dont quit the application, so I quit and restart, and it will (probaly) dont work again...
This happens on both debug and normal layer...this happens doesnt matter if the box is null or no, and if the rowpitch is null or not...

btw, can someone explain me what should go in the rowpich?(since my buffer is a vertex buffer..)

Share this post


Link to post
Share on other sites
Just curious, are you doing this for some sort of smooth vertex animation or morphing?

And, this behavior sounds bit more like the use of uninitialized memory. Are you saying that your app always starts out by not working, and then randomly starts working and stays working until you restart?

Share this post


Link to post
Share on other sites
Im doing this because I want display any number of meshs I want, and all of they have the same layout/format..isnt this a motive for use update subresource?

And no, it doesnt starts working, or it works, or it dont, never both on the same execution.

I alredy asked something like this before, the thing is, since you have a buffer count limit to use, you have to use the same buffer to display lots of stuff, its just that what Im trying to do, reuse the buffer with a new mesh everytime I want. Since its the same format/layout, Im trying to use updatesubresource(and not Map).

Im also not putting everything on the same buffer at once because I want each mesh to have its own world transformations...

Theres any mistake on this concept? Thats how I understand the pipeline...(displaying just one mesh is easy, now I want a entire scene).

Share this post


Link to post
Share on other sites
So I would use UpdateSubResource only to modify a small part of a buffer while maintaining the data surrounding it, for instance deforming part of a mesh or splatting a texture. Using update subresource may cause the driver to allocate temporary space to store your data due to dependencies of the resource by pending commands in the gpu buffer. Updating the same location in a resource several times a frame in this way will result in worst case performance. UpdateSubResource can perform very well if the driver can schedule the transfer immediately and if there are no pending commands (at least 2 frames worth) that require the data you're trying to overwrite. There's not much you can do about the first. For the second you may make the determination based on your algorithm and how long ago that data was last used, or by keeping track of dependencies by using a query to determine when the gpu is finished with a task.

You can create quite a number of vertex buffers, but creating a couple large ones and then packing them with data is certainly best. You don't want to have to upload the same data more than once if that's at all possible -- you want to limit the amount of data that needs to be moved to the GPU each frame in order to maximize performance. If you have to stream objects in and out then you'll have to work out a way to consolidate or fill holes in the resource.

What you're describing here sounds like a good fit for using Map with a dynamic vertex buffer. Dynamic buffers are designed to provide the fastest path for getting large chunks of new data to the GPU. They also prevent the need for temporary storage allocation and allow the GPU to decide the best scheduling for the transfer. Recommendations will vary depending on many factors so I'll just suggest a few. But the key here is to use Map append.

Simple option:
Once data is on the gpu it can stay there since we're not worried about running out of space. Allocate a very large dynamic buffer and just append new models to it as they are needed. This approach means that you won't use DISCARD since that will cause previously written data in the buffer to be lost. Drawing will require you to know the offsets of each model in the buffer.

More Complicated:
Objects need to be streamed in and have a variable lifetime on the GPU. In this case I would use the dynamic vertex buffer to get data to the GPU, and then do a gpu copy of the new data to a very large default resource in order to maintain it long term. Drawing will still require you to know the offsets into the vertex buffer for each model. The same offsets can also be used to keep track of free spaces as they open up. Depending on how much streaming you end up doing, you will probably have to consolidate the data occasionally to prevent fragmentation. Make sure that the dynamic buffer is large enough to contain all data that you want to stream over the course of at least 2-4 frames so that you don't have to call discard too often.

Share this post


Link to post
Share on other sites
Dude, this map is so more complex than the old lock or Im getting dumber with experience?..

Doesnt the old lock method returns a pointer to a pointer to the data, so u could just update the data by updating the address pointed to(since is a pointer to a pointer, and not a pointer to the data)..

Now you just cant do it? I will have to update all the data pointed to one by one? I hope Im wrong(probaly).

I mean I cant do this:

D3D11_MAPPED_SUBRESOURCE newdata_map; ZeroMemory( &newdata_map, sizeof(D3D11_MAPPED_SUBRESOURCE) );
if( pDIContext_p->Map( pVBuff_p, 0, D3D11_MAP_WRITE_DISCARD, NULL, &newdata_map )!= S_OK ) return E_FAIL;
newdata_map.pData = pV_p;
pDIContext_p->Unmap( pVBuff_p, 0 );



neither this:( this copies just the index[0] on the array right?)

D3D11_MAPPED_SUBRESOURCE newdata_map; ZeroMemory( &newdata_map, sizeof(D3D11_MAPPED_SUBRESOURCE) );

if( pDIContext_p->Map( pVBuff_p, 0, D3D11_MAP_WRITE_DISCARD, NULL, &newdata_map )!= S_OK ) return E_FAIL;
vposnormaltexmaterial * pData_SRC = (vposnormaltexmaterial*)pV_p;
vposnormaltexmaterial * pData_DST = (vposnormaltexmaterial*)newdata_map.pData;
*pData_DST = *pData_SRC;
pDIContext_p->Unmap( pVBuff_p, 0 );



Just that seems to work:

D3D11_MAPPED_SUBRESOURCE newdata_map; ZeroMemory( &newdata_map, sizeof(D3D11_MAPPED_SUBRESOURCE) );

if( pDIContext_p->Map( pVBuff_p, 0, D3D11_MAP_WRITE_DISCARD, NULL, &newdata_map )!= S_OK ) return E_FAIL;

memcpy( newdata_map.pData, pV_p, iRowPitch_aka_Width );
pDIContext_p->Unmap( pVBuff_p, 0 );




Am I doing what is suppose to do?(im using discard now to make my life easier)
Isnt that much less efficient than the lock method?

Share this post


Link to post
Share on other sites
The pointer returned when calling Map() is the location of the resource on the CPU side. You should memcpy or write your vertex data directly to this memory (making sure not to exceed the resource size) and then Unmap it.

Mapping a dynamic resource many times a frame with D3D11_MAP_WRITE_NO_OVERWRITE will not incur any additional cost. In this scenario you just want to append data to the buffer. Data already in the buffer is still usable by the GPU and unaffected by the call to Map (no locking involved). Of course you have to keep track of where the current 'end' to the buffer is. Mapping with D3D11_MAP_WRITE_DISCARD means that a new buffer will be allocated for you (also no locking involved).

Dynamic resources have a CPU side space and a GPU side space. The CPU side resource makes Mapping them cheap for write new data to them. Later on when you go to use the data, the driver will figure out that it needs do a transfer to the GPU and do so in the most efficient way possible. The driver will also ensure that it only transferred the data that was actually needed to draw the model. So essentially the driver is keeping track of what parts of the dynamic buffer are valid and managing a few things for you.

The transfer is one way, calling discard invalidates everything in the buffer and essentially resets the drivers information about the resource.

Share this post


Link to post
Share on other sites
The D3D11.h file has a set of #defines at the top indicating all of the limits/bounds of the API. It contains D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM which is 128 meg. You might be able to create something larger but that depends on if the driver wants to let you.

Share this post


Link to post
Share on other sites
DieterVW, so just to double-check, the best way to render a scene is to have big dynamic vertex/index buffers per input layout that are filled on the fly each frame as opposed to storing the geometry on a per mesh basis, right?

Share this post


Link to post
Share on other sites
There are several things involved in answering the question of what is best.

Packing several models with the same layout into a single buffer, whether it is dynamic, immutable, or default, should have some gains since it can be left bound to the pipeline for more draw calls and it fragments memory less.

I only recommend dynamic buffers for model data that needs changing on a relatively frequent basis. You do not want to be uploading the same model data to the GPU every frame, so data that will persist for a while should be moved out of the dynamic buffer and into a default buffer.

Share this post


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

  • Advertisement
  • Advertisement
  • Popular Now

  • Advertisement
  • Similar Content

    • By AxeGuywithanAxe
      I wanted to see how others are currently handling descriptor heap updates and management.
      I've read a few articles and there tends to be three major strategies :
      1 ) You split up descriptor heaps per shader stage ( i.e one for vertex shader , pixel , hull, etc)
      2) You have one descriptor heap for an entire pipeline
      3) You split up descriptor heaps for update each update frequency (i.e EResourceSet_PerInstance , EResourceSet_PerPass , EResourceSet_PerMaterial, etc)
      The benefits of the first two approaches is that it makes it easier to port current code, and descriptor / resource descriptor management and updating tends to be easier to manage, but it seems to be not as efficient.
      The benefits of the third approach seems to be that it's the most efficient because you only manage and update objects when they change.
    • By evelyn4you
      hi,
      until now i use typical vertexshader approach for skinning with a Constantbuffer containing the transform matrix for the bones and an the vertexbuffer containing bone index and bone weight.
      Now i have implemented realtime environment  probe cubemaping so i have to render my scene from many point of views and the time for skinning takes too long because it is recalculated for every side of the cubemap.
      For Info i am working on Win7 an therefore use one Shadermodel 5.0 not 5.x that have more options, or is there a way to use 5.x in Win 7
      My Graphic Card is Directx 12 compatible NVidia GTX 960
      the member turanszkij has posted a good for me understandable compute shader. ( for Info: in his engine he uses an optimized version of it )
      https://turanszkij.wordpress.com/2017/09/09/skinning-in-compute-shader/
      Now my questions
       is it possible to feed the compute shader with my orignial vertexbuffer or do i have to copy it in several ByteAdressBuffers as implemented in the following code ?
        the same question is about the constant buffer of the matrixes
       my more urgent question is how do i feed my normal pipeline with the result of the compute Shader which are 2 RWByteAddressBuffers that contain position an normal
      for example i could use 2 vertexbuffer bindings
      1 containing only the uv coordinates
      2.containing position and normal
      How do i copy from the RWByteAddressBuffers to the vertexbuffer ?
       
      (Code from turanszkij )
      Here is my shader implementation for skinning a mesh in a compute shader:
      1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 struct Bone { float4x4 pose; }; StructuredBuffer<Bone> boneBuffer;   ByteAddressBuffer vertexBuffer_POS; // T-Pose pos ByteAddressBuffer vertexBuffer_NOR; // T-Pose normal ByteAddressBuffer vertexBuffer_WEI; // bone weights ByteAddressBuffer vertexBuffer_BON; // bone indices   RWByteAddressBuffer streamoutBuffer_POS; // skinned pos RWByteAddressBuffer streamoutBuffer_NOR; // skinned normal RWByteAddressBuffer streamoutBuffer_PRE; // previous frame skinned pos   inline void Skinning(inout float4 pos, inout float4 nor, in float4 inBon, in float4 inWei) {  float4 p = 0, pp = 0;  float3 n = 0;  float4x4 m;  float3x3 m3;  float weisum = 0;   // force loop to reduce register pressure  // though this way we can not interleave TEX - ALU operations  [loop]  for (uint i = 0; ((i &lt; 4) &amp;&amp; (weisum&lt;1.0f)); ++i)  {  m = boneBuffer[(uint)inBon].pose;  m3 = (float3x3)m;   p += mul(float4(pos.xyz, 1), m)*inWei;  n += mul(nor.xyz, m3)*inWei;   weisum += inWei;  }   bool w = any(inWei);  pos.xyz = w ? p.xyz : pos.xyz;  nor.xyz = w ? n : nor.xyz; }   [numthreads(1024, 1, 1)] void main( uint3 DTid : SV_DispatchThreadID ) {  const uint fetchAddress = DTid.x * 16; // stride is 16 bytes for each vertex buffer now...   uint4 pos_u = vertexBuffer_POS.Load4(fetchAddress);  uint4 nor_u = vertexBuffer_NOR.Load4(fetchAddress);  uint4 wei_u = vertexBuffer_WEI.Load4(fetchAddress);  uint4 bon_u = vertexBuffer_BON.Load4(fetchAddress);   float4 pos = asfloat(pos_u);  float4 nor = asfloat(nor_u);  float4 wei = asfloat(wei_u);  float4 bon = asfloat(bon_u);   Skinning(pos, nor, bon, wei);   pos_u = asuint(pos);  nor_u = asuint(nor);   // copy prev frame current pos to current frame prev pos streamoutBuffer_PRE.Store4(fetchAddress, streamoutBuffer_POS.Load4(fetchAddress)); // write out skinned props:  streamoutBuffer_POS.Store4(fetchAddress, pos_u);  streamoutBuffer_NOR.Store4(fetchAddress, nor_u); }  
    • By mister345
      Hi, can someone please explain why this is giving an assertion EyePosition!=0 exception?
       
      _lightBufferVS->viewMatrix = DirectX::XMMatrixLookAtLH(XMLoadFloat3(&_lightBufferVS->position), XMLoadFloat3(&_lookAt), XMLoadFloat3(&up));
      It looks like DirectX doesnt want the 2nd parameter to be a zero vector in the assertion, but I passed in a zero vector with this exact same code in another program and it ran just fine. (Here is the version of the code that worked - note XMLoadFloat3(&m_lookAt) parameter value is (0,0,0) at runtime - I debugged it - but it throws no exceptions.
          m_viewMatrix = DirectX::XMMatrixLookAtLH(XMLoadFloat3(&m_position), XMLoadFloat3(&m_lookAt), XMLoadFloat3(&up)); Here is the repo for the broken code (See LightClass) https://github.com/mister51213/DirectX11Engine/blob/master/DirectX11Engine/LightClass.cpp
      and here is the repo with the alternative version of the code that is working with a value of (0,0,0) for the second parameter.
      https://github.com/mister51213/DX11Port_SoftShadows/blob/master/Engine/lightclass.cpp
    • By mister345
      Hi, can somebody please tell me in clear simple steps how to debug and step through an hlsl shader file?
      I already did Debug > Start Graphics Debugging > then captured some frames from Visual Studio and
      double clicked on the frame to open it, but no idea where to go from there.
       
      I've been searching for hours and there's no information on this, not even on the Microsoft Website!
      They say "open the  Graphics Pixel History window" but there is no such window!
      Then they say, in the "Pipeline Stages choose Start Debugging"  but the Start Debugging option is nowhere to be found in the whole interface.
      Also, how do I even open the hlsl file that I want to set a break point in from inside the Graphics Debugger?
       
      All I want to do is set a break point in a specific hlsl file, step thru it, and see the data, but this is so unbelievably complicated
      and Microsoft's instructions are horrible! Somebody please, please help.
       
       
       

    • By mister345
      I finally ported Rastertek's tutorial # 42 on soft shadows and blur shading. This tutorial has a ton of really useful effects and there's no working version anywhere online.
      Unfortunately it just draws a black screen. Not sure what's causing it. I'm guessing the camera or ortho matrix transforms are wrong, light directions, or maybe texture resources not being properly initialized.  I didnt change any of the variables though, only upgraded all types and functions DirectX3DVector3 to XMFLOAT3, and used DirectXTK for texture loading. If anyone is willing to take a look at what might be causing the black screen, maybe something pops out to you, let me know, thanks.
      https://github.com/mister51213/DX11Port_SoftShadows
       
      Also, for reference, here's tutorial #40 which has normal shadows but no blur, which I also ported, and it works perfectly.
      https://github.com/mister51213/DX11Port_ShadowMapping
       
  • Advertisement