Pass int array to the pixel shader

I want to pass an int array to the pixel shader.  I used SetIntArray(name, val)..the problem is that in the shader I do not know the exact size of the array, therefore in declaring it i am trying to use an int *.  It seems as if the compiler does not like this.

Is is it possible to use pointers in the shader   If not how can I pass a variable length array to the shader

can someone give me an example of the usage of this function


Answer this question

Pass int array to the pixel shader

  • Mark Sutton

     Sando the Imperial Khan wrote:
    I need to render my output to a texture instead of to the screen.  Can you point me to a suitable tutorial or give me an example

    The technique you're after is commonly referred to as "render to texture". I can't think of any particular tutorials, but Google found stuff.

    RtT is very commonly associated with "post processing" effects - so if you can't find much from a straight search, try looking for that instead. For starters, theres the PostProcess sample in the SDK.

     Sando the Imperial Khan wrote:
    I want to store some computed values to the texture so that after the pixel shading I can retrieve these values for analysis and other computations.

    Sounds fair enough, but you might well want to consider the performance of your system... Reading graphics data back from the GPU can be *very* slow. Such that, for a small data-set you could spend more time reading back than you do computing Smile

    hth
    Jack


  • Anton Klimov - MSFT

    I found a tutorial from google.  I followed it and try to implement it in my code. the following is a snippet of my code. after executing it I get a

    hr=D3DERR_INVALIDCALL (0x8876086c) Error

    This occurs on the create texture line

    V( pd3dDevice->CreateTexture(200, 200, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pMatrixTexture, NULL) );

    /** Fill Matrix here **/

    D3DLOCKED_RECT lockedRect;

    V( pMatrixTexture->LockRect(0,&lockedRect,NULL,0));

    ....

    V( pMatrixTexture->UnlockRect(0));

    pMatrixTexture->GetSurfaceLevel(0,&pResultSurface);

    For some reason it cannot create the texture.  What could be causing this and can u give me a solution for this



  • Sanjay12345

    Can you give me an example of creating a texture and passing it into the shader

    for example a vector that has 200 elements.

    a vector is a 200 x 1 array (1dimensional)

  • sp00k113

    I'm pretty sure it's due to you specifying D3DPOOL_MANAGED and D3DUSAGE_RENDERTARGET - they're incompatible:
    The resource will be a render target. D3DUSAGE_RENDERTARGET can only be used with D3DPOOL_DEFAULT.


    As a general note, if you enable the debug runtimes then you're likely to get better descriptions of why the function call failed. Have a look at this NeXe entry if you're unfamiliar with the debug runtimes.

    hth
    Jack

  • ploaiza

    You can't use pointers in a shader (well, not in the way you're wanting...) - HLSL might look very C/C++ like, but it's nowhere near as powerful Smile

    Also, unless you choose to send your array data as a texture you'll be very limited by the number of constant registers that you can put data into. Which is partly why you'll want to declare a size (as a multiple of float4's)...

    hth
    Jack


  • s3ng

    unfortunately i'm having the same problem. i created a texture that is supposed to be used as an render target:

    ...
    IDirect3DTexture9* pT;
    ...
    pDevice->CreateTexture(WIDTH, HEIGHT, 0, D3DUSAGE_RENDERTARGET,
    D3DFMT_G16R16, D3DPOOL_DEFAULT, &pT, NULL);
    ...


    but i can't use pDevice->SetRenderTarget() to set the create texture from above as a render target, see the parameters of SetRenderTarget():
    HRESULT SetRenderTarget(
    DWORD RenderTargetIndex,
    IDirect3DSurface9* pRenderTarget
    );

    does anybody know a solution to this problem i've looked on the web quite a bit.. maybe i'm just adressing the problem from the wrong way

  • VC_Learner

    I thought it was that but then I don not know of any other way of performing the lockRect function the the texture.  This can only be done if it is D3DPOOL_MANAGED, it cannot be done on D3DPOOL_DEFAULT.

    Is there any work around that you know of to populate the texture


  • Anthony Stanley

    Thanks jack for your reply.

    I need to render my output to a texture instead of to the screen.  Can you point me to a suitable tutorial or give me an example

    I want to store some computed values to the texture so that after the pixel shading I can retrieve these values for analysis and other computations.

  • chris dunn

     Sando the Imperial Khan wrote:
    Jack do u mind giving a sample of this, with respect to what we having been asking so far

    Well it was sort of due to reading between the lines - so it might not be directly relevant Smile

    For image reproduction it'll rarely be a problem - usually slight inaccuracies are tolerable, and in most cases having some sort of interpolation is actually a good thing as you can get away with storing less data.

    However, if you were to be doing scientific work on a GPU (www.gpgpu.org has lots of examples of this) then accuracy and interpolation become issues. If you were doing vector/matrix type operations (larger than the built in 4x4 type stuff) then it doesn't really make sense to have a "half way" value between two elements in a vector as it should be a discreet list of values...

    hth
    Jack



  • Moshe Gottlieb

    Jack could expound further on the aspect of point filtering that you alluded to in the posting above.

  • Juvraj

    Right, this could be quite involved Smile ask for more details if you need them...

    1. Choose your texture format
    In D3D9 there isn't really an integer format that matches a regular 32bit "int" in C/C++. Check out the list of formats for more details. I'm going to pick D3DFMT_L16 - from looking at the capabilities list, anything that can handle a shader seems to be okay with an L16 texture. BUT it's obviously half the resolution of a 32bit integer.

    2. Create the texture using IDirect3DDevice9::CreateTexture( ):

    if( FAILED( pDevice->CreateTexture( 200, 1, 1, 0, D3DFMT_L16, D3DPOOL_DEFAULT,  &pTexture, NULL ) ) )
    {
        // Handle failure here.
    }

     

    Notes: You should probably stick to a 2N dimension - even if that means "padding" out to some unused elements. Also, you should check the device formats and supported texture sizes... the above fragment will work on most of the hardware you'll meet, but there's *no* guarantee... especially the D3DFMT_L16 part.

    2. Fill the texture
    You can either do this manually using IDirect3DTexture9::LockRect() or with the helper function D3DXFillTexture( ). The former is more complicated, but you've got more control on how the 32bit integer is encoded. The latter is easier to use, but it's working at floating-point precision, so it's more tricky to get things lined up correctly.

    2. Use point filtering
    If you want the *real* values you stored to be the only ones you can get back out, turn on point filtering - that way you wont (if you mis-address texels) get a mixture of neighbouring values.

    3. Address values in the texture
    Given you mention the use of the effects framework, I presume you know how to handle the rest - just set the created texture as an input and off you go. You might need to pass in some parameters to the shader to get the correct mapping (or author your vertex data accordingly)...

    hth
    Jack




  • HдLΛвί

    You can use IDirect3DDevice9::GetRenderTargetData( ) to copy a render-target texture to a system memory surface such that you can read from it.

    Although, are you definitely wanting to lock the render target I thought this thread was about passing in an arbitrary large "array" of data in for the shader to work on. If so, then you shouldn't need to define the texture as a render-target. Only the output needs to be defined as a render target, not the input...

    hth
    Jack


  • Ed Draper

     Kirk Barham wrote:
    Jack could expound further on the aspect of point filtering that you alluded to in the posting above.

    Sure... you mean this one :
     Jack Hoxley wrote:
    2. Use point filtering
    If you want the *real* values you stored to be the only ones you can get back out, turn on point filtering - that way you wont (if you mis-address texels) get a mixture of neighbouring values.

    The "problem" with texture filtering is that, when enabled and the hardware supports it, correct operation is to sample more than one texel. The actual "colour" (or just raw value in this case) is defined as the very center point of the pixel - if you don't address it exactly you'll get a combination of the neighbouring pixels. Even if you get it 0.1 out then you might end up with 90% of the correct value but still 10% of the neighbour.

    When precision is important and you want to make sure you're operating on the values you put in the texture this can be an easy source of bugs. Small rounding errors and general imprecision can (over a number of operations) end up in a significantly incorrect answer - despite the fact that code represents the exact mathematics you wanted.

    So, a solution to this is to disable texture filtering. By using point filtering it'll just pick the value closest to the texture coordinate you provided. No blending with neighbours occurs. That means (with reference to my previous example) you can't get the 90%:10% mix - you've got a much higher margin for texture-coordinate error. The only error that you should be able to introduce is if you get the texture coordinates completely wrong and end up addressing the neighbouring pixel instead - but that should be easier to debug.

    That help

    Jack



  • Omprakash

    Jack do u mind giving a sample of this, with respect to what we having been asking so far

  • Pass int array to the pixel shader