Jump to content

  • Log In with Google      Sign In   
  • Create Account


Difference between two ways of assigning values to variables in HLSL constant buffer


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 wngabh11   Members   -  Reputation: 128

Like
0Likes
Like

Posted 12 February 2013 - 01:47 AM

As far as I know, There are two way passing values to variables in HLSL constant buffer.
 

 
cbuffer cbGeometryRender : register( b0 )
{
    float4x4 WorldMatrix;
    float4x4 ViewMatrix;
    float4x4 ProjMatrix;
    float4x4 WVPMatrix;
    float4x4 VPMatrix;    
    float3 EyePos;
    float3 LightDir; // start at the sun
    float4 SplitPos;
};

 

 

 
The first way is to use Effect11 Library. For example

 
ID3DX11Effect *pEffect; // initialize when compiling the fx file
ID3DX11EffectVectorVariable *pEyePos = pEffect->GetVariableByName("EyePos")->AsVector();
pEyePos->SetFloatVector(......);

 

 

 
The second way is to use the constant buffer created with the desc in the following.

 D3D11_BUFFER_DESC bd;
 bd.Usage = D3D11_USAGE_DYNAMIC;
 bd.ByteWidth = sizeof( CONSTANT_BUFFER_STRUCT );
 bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
 bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
 bd.MiscFlags = 0;
 hr = pd3dDevice->CreateBuffer( &bd, NULL, &g_pCB ); 

 

 

On each frame, we map g_pCB to b0, assign the values, and then unmap it. After that, We set constant buffer for each stage.

 

IS Anyone who know what the differences are between these two methods?

which is better?

can Effect11 Library be used with deferred context?

 

Can these two ways be used together, i.e., using Effect Library compile the fx file and using the second way to pass the value to GPU?


Edited by wngabh11, 12 February 2013 - 02:01 AM.


Sponsor:

#2 MJP   Moderators   -  Reputation: 10858

Like
1Likes
Like

Posted 12 February 2013 - 02:11 AM

The effects framework is just a wrapper on top of core D3D11 functionality. Ultimately it will create, map, and bind buffers just like you've described in your second way. If you step through the calls in your debugger or capture a frame in PIX you'll be able to see what it's doing. The main difference is that it might be more convenient than dealing with the buffer manually, although it may consume more resources and/or do things in a sub-optimal way.



#3 wngabh11   Members   -  Reputation: 128

Like
0Likes
Like

Posted 12 February 2013 - 03:20 AM

Thanks for help. 

I try to mix two way together. In each frame, I do things in the following order:

 

IASetInputLayout

IASetPrimitiveTopology

ID3DX11EffectTechnoque->GetPassByIndex(0)->Apply( 0, DeviceContext );

Map constant buffer

assign values

Umap constant buffer

VSSetConstantBuffer

PSSetConstantBuffer

IASetVertexBuffer

IASetIndexBuffer

 

DrawIndex

 

But If i render in the order above, I cannot pass the values correctly and thereby cannot render correct things.

Is the order wrong? Or I cannot mix the two ways?



#4 mhagain   Crossbones+   -  Reputation: 7812

Like
0Likes
Like

Posted 12 February 2013 - 05:41 PM

The Effects11 source code is available and can be examined; you'll find it at e.g. C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\C++\Effects11

 

Looking through how it handles cbuffer updates, the way it works is that it builds a chunk of memory representing the cbuffer data, then each Effect->Set call will root through that and copy your data to the appropriate place (setting a dirty flag while doing so), like so:

 

template<typename IBaseInterface, BOOL IsAnnotation>
HRESULT TIntScalarVariable<IBaseInterface, IsAnnotation>::SetFloat(float Value)
{
    LPCSTR pFuncName = "ID3DX11EffectScalarVariable::SetFloat";
    if (IsAnnotation) return AnnotationInvalidSetCall(pFuncName);
    DirtyVariable();
    return CopyScalarValue<ETVT_Float, ETVT_Int, float, FALSE>(Value, Data.pNumericInt, pFuncName);
}

 

Then, before draw calls are issued, it checks if the dirty flag is set and if so it uploads the entire buffer via UpdateSubresource, like so:

 

// Update constant buffer contents if necessary
D3DX11INLINE void CheckAndUpdateCB_FX(ID3D11DeviceContext *pContext, SConstantBuffer *pCB)
{
    if (pCB->IsDirty && !pCB->IsNonUpdatable)
    {
        // CB out of date; rebuild it
        pContext->UpdateSubresource(pCB->pD3DObject, 0, NULL, pCB->pBackingStore, pCB->Size, pCB->Size);
        pCB->IsDirty = FALSE;
    }
}

 

You can probably do a little better than that yourself (you can also do much worse if you don't manage your cbuffers properly, of course).

 

It's probably not a good idea to mix the two ways as all it takes is one dirty flag (i.e. one cbuffer variable set via Effects) to cause the entire cbuffer to be marked dirty, which will stomp over anything you set yourself.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS