can't output DEPTH in a fragment program

Problems building or running the engine, queries about how to use features etc.

can't output DEPTH in a fragment program

Postby Thieum » Wed Mar 05, 2008 2:55 pm

Hi!
I am trying to write depth in the Z-Buffer with this minimal pixel shader :
Code: Select all
void TerrainDecalFP(
   out float4 oColor : COLOR,
   out float oDepth : DEPTH
)
{
   oColor = 1;
   oDepth = 1;
}

but when the material is loaded I get this error
Code: Select all
(15): error X2022: scalar registers cannot be masked

There is two strange thing : the Cg file containing the function is only 9 lines long but the error says "(15)" and the exception raised by the error shows an error box whereas other cg compilation errors are just written in the log

The shader is compiled with the ps_2_0 profile and there is only a call to the shader in the material.
This shader works with XSI's real-time materials, then can this be an OGRE bug ?
User avatar
Thieum
Gnome
 
Posts: 342
Kudos: 2
Joined: 26 Apr 2006
Location: Bordeaux, France

Postby sinbad » Wed Mar 05, 2008 5:27 pm

That message is coming from the Cg compiler, not Ogre.

I've tried this and it works fine. Please post how you've declared the shader.
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
 
Posts: 19261
Kudos: 69
Joined: 06 Oct 2002
Location: Guernsey, Channel Islands

Postby Thieum » Thu Mar 06, 2008 9:54 am

here is the declaration :
Code: Select all
fragment_program TerrainDecalFP cg
{
   source TerrainDecal2.cg
   entry_point TerrainDecalFP
   profiles ps_2_0
}

material decal
{
   technique
   {
      pass
      {
         fragment_program_ref TerrainDecalFP
         {   
         }
      }
   }
}

As I said, it is minimal. I also tested it outside OGRE and it worked too.
User avatar
Thieum
Gnome
 
Posts: 342
Kudos: 2
Joined: 26 Apr 2006
Location: Bordeaux, France

Postby iloseall » Thu Mar 06, 2008 12:43 pm

Maybe you has two files named "TerrainDecal2.cg".
Try to search TerrainDecal2.cg.
User avatar
iloseall
Gremlin
 
Posts: 156
Kudos: 0
Joined: 14 Sep 2003
Location: Beijing China

Postby Thieum » Thu Mar 06, 2008 4:30 pm

I'am afraid this is the only file with this name. If i remove the "oDepth = 1;" line from the script, there is no longer an error.
User avatar
Thieum
Gnome
 
Posts: 342
Kudos: 2
Joined: 26 Apr 2006
Location: Bordeaux, France

Postby Caelin » Sat Apr 26, 2008 11:21 pm

I am getting the same problem with a tech demo I am trying to create. Currently I am taking the deferred shading demo and translating it in to cg instead of using HLSL and GLSL. I would rather just use cg so I only have to learn the syntax for the one language. One problem I am running in to however is the ambient lighting pixel shader outputs depth and I am getting the same error from it. I enabled logging on the cg program manager plugin and it is showing that cg is compiling the depth output as a float3 instead of a plain float like it should. I am still working on seeing if I can try to get cg to compile depth as a single float scalar but figured I would post here and let everyone know what I had found. Also here is a snippet from the log of the plugin compiling the ambient lighting shader I was using along with the actual cg code.


Cg Code
Code: Select all
struct AMBIENTOUTPUT
{
   float4 Color : COLOR;
   float Depth : DEPTH;
};

AMBIENTOUTPUT AmbientLightingP( float2 TexCoord: TEXCOORD0,
           float3 ProjCoord: TEXCOORD1,

         uniform float4x4 Proj,
         uniform float4 AmbientColor,
         uniform sampler2D Tex0 : register(s0),
         uniform sampler2D Tex1 : register(s1),
         uniform sampler2D Tex2 : register(s2),
         uniform sampler2D Tex3 : register(s3) )
{
   // Load GBuffer in to structure;
   GBUFFER In;
   LoadGBuffer( In, TexCoord, Tex0, Tex1, Tex2, Tex3 );

   // Clip fragment if depth is too close, so the skybox can be rendered on the background
   float Depth = GetDepth( In );
   clip( Depth - 5.0f );

   AMBIENTOUTPUT Out;
   // Calculate ambient colour of fragment
   Out.Color = float4(AmbientColor * GetDiffuse( In ), 0.0f);

   // Calculate depth of fragment;
   Out.Depth = ProjCoord.z * Proj[2][2] + Proj[2][3] / Depth;
   
   return Out;
}



Log output
Code: Select all
16:08:24: ps_3_0
// cgc version 2.0.0010, build date Dec 12 2007
// command line args: -q -profile ps_3_0 -entry AmbientLightingP
//vendor NVIDIA Corporation
//version 2.0.0.10
//profile ps_3_0
//program AmbientLightingP
//semantic AmbientLightingP.Proj
//semantic AmbientLightingP.AmbientColor
//semantic AmbientLightingP.Tex0 : TEXUNIT0
//semantic AmbientLightingP.Tex1 : TEXUNIT1
//semantic AmbientLightingP.Tex2 : TEXUNIT2
//semantic AmbientLightingP.Tex3 : TEXUNIT3
//var float2 TexCoord : $vin.TEXCOORD0 : ATTR0 : 0 : 1
//var float3 ProjCoord : $vin.TEXCOORD1 : ATTR1 : 1 : 1
//var float4x4 Proj :  : c[0], 4 : 2 : 1
//var float4 AmbientColor :  : c[4] : 3 : 1
//var sampler2D Tex0 : TEXUNIT0 : texunit 0 : 4 : 1
//var sampler2D Tex1 : TEXUNIT1 : texunit 1 : 5 : 0
//var sampler2D Tex2 : TEXUNIT2 : texunit 2 : 6 : 0
//var sampler2D Tex3 : TEXUNIT3 : texunit 3 : 7 : 1
//var float4 AmbientLightingP.Color : $vout.COLOR : COL : -1 : 1
//var float3 AmbientLightingP.Depth : $vout.DEPTH : DEPR : -1 : 1
//var <none>4 $kill_0000 : $vout.$kill : $kill : -1 : 0
//const c[5] = 65536 0.00390625 256 -1
//const c[6] = 1.5258789e-005 -5 0 1
dcl_2d s0
dcl_2d s3
def c5, 65536.00000000, 0.00390625, 256.00000000, -1.00000000
def c6, 0.00001526, -5.00000000, 0.00000000, 1.00000000
dcl_texcoord0 v0.xy
dcl_texcoord1 v1.xyz
texld r0.xy, v0, s0
mul r0.z, r0.y, c5.x
mul r0.w, r0.z, c5.y
abs r0.w, r0
frc r0.w, r0
mul r0.w, r0, c5.z
cmp r0.z, r0, r0.w, -r0.w
mad r0.y, -r0.z, c6.x, r0
add r0.w, r0.z, c5
mul r0.w, r0, r0
rcp r0.z, r0.w
mad r0.x, r0.y, c6, r0
mul r0.x, r0, r0.z
add r0.y, r0.x, c6
cmp r0.y, r0, c6.z, c6.w
mov_pp r1, -r0.y
rcp r0.x, r0.x
mul r0.w, r0.x, c2
texld r0.xyz, v0, s3
texkill r1.xyzw
mad oDepth.z, v1.z, c2.z, r0.w
mul oC0.xyz, r0, c4
mov oC0.w, c6.z
Caelin
Gnoblar
 
Posts: 5
Kudos: 0
Joined: 20 Apr 2008

Postby Caelin » Sat Apr 26, 2008 11:55 pm

I found a post on the cg forums stating that this is a bug with the code generation of cgc that is specific to D3D. So this has nothing to do with Ogre and is actually a problem with the cg toolkit. Here is the link to the post.

http://developer.nvidia.com/forums/inde ... #entry2378
Caelin
Gnoblar
 
Posts: 5
Kudos: 0
Joined: 20 Apr 2008

Postby Thieum » Mon Apr 28, 2008 8:41 am

Thanks for the answer!
User avatar
Thieum
Gnome
 
Posts: 342
Kudos: 2
Joined: 26 Apr 2006
Location: Bordeaux, France

Postby _tommo_ » Sun May 04, 2008 7:20 pm

I also have this problem...
so, knowing that it's a CG bug, what we could do to avoid it?
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
_tommo_
Gnoll
 
Posts: 677
Kudos: 3
Joined: 19 Sep 2006

Postby Caelin » Mon May 05, 2008 5:53 am

_tommo_ wrote:I also have this problem...
so, knowing that it's a CG bug, what we could do to avoid it?


I added a couple of lines to the D3D9_RenderSystem plugin to patch the problem as a temporary fix until the CG compiler is fixed. Hopefully this is in the next patch. To fix this issue I just replaced the oDepth.z with oDepth using a simple find and replace. I did this in the D3D9GpuProgram::loadFromSource function in the file OgreD3D9GpuProgram.cpp. The following code is the original function and then the modified version.

Original Function
Code: Select all
void D3D9GpuProgram::loadFromSource(void)
{
    // Create the shader
    // Assemble source into microcode
    LPD3DXBUFFER microcode;
    LPD3DXBUFFER errors;
      
    HRESULT hr = D3DXAssembleShader(
        mSource.c_str(),
        static_cast<UINT>(mSource.length()),
        NULL,               // no #define support
        NULL,               // no #include support
        0,                  // standard compile options
        &microcode,
        &errors);

    if (FAILED(hr))
    {
        String message = "Cannot assemble D3D9 shader " + mName + " Errors:\n" +
        static_cast<const char*>(errors->GetBufferPointer()) + "\nSource:\n" + mSource.c_str();
        errors->Release();
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
                "D3D9GpuProgram::loadFromSource");
           
    }

    loadFromMicrocode(microcode);

    SAFE_RELEASE(microcode);
    SAFE_RELEASE(errors);
}



"Fixed" Function
Code: Select all
void D3D9GpuProgram::loadFromSource(void)
{
    // Create the shader
    // Assemble source into microcode
    LPD3DXBUFFER microcode;
    LPD3DXBUFFER errors;
      
    // Fix issue with DEPTH output in fragment programs for D3D code generation in CG
    size_t idx = 0;
    while( (idx=mSource.find( "oDepth.z", idx )) != std::string::npos )
    {
        mSource.replace( idx, 8, "oDepth" );
    }
      
    HRESULT hr = D3DXAssembleShader(
        mSource.c_str(),
        static_cast<UINT>(mSource.length()),
        NULL,               // no #define support
        NULL,               // no #include support
        0,                  // standard compile options
        &microcode,
        &errors);

    if (FAILED(hr))
    {
        String message = "Cannot assemble D3D9 shader " + mName + " Errors:\n" +
        static_cast<const char*>(errors->GetBufferPointer()) + "\nSource:\n" + mSource.c_str();
        errors->Release();
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
                "D3D9GpuProgram::loadFromSource");
           
    }

    loadFromMicrocode(microcode);

    SAFE_RELEASE(microcode);
    SAFE_RELEASE(errors);
}
Caelin
Gnoblar
 
Posts: 5
Kudos: 0
Joined: 20 Apr 2008

Re: can't output DEPTH in a fragment program

Postby Aldous11 » Thu Sep 16, 2010 5:47 am

FX Composer is quite a bit different from ARB_FRAGMENT_PROGRAM; the output bindings are not analogous. The fragment program you have looks fine, though you should make sure that there are no errors generated from reading it in (which it looks like you do.)

Here's why the fragment program you have is valid, from the spec:

Code:

Code: Select all
If a fragment program does not write a color value, what should
    be the final color of the fragment?

      RESOLVED: The final fragment color is undefined.  Note that it may
      be perfectly reasonable to have a program that computes depth
      values but not colors.  Fragment colors are often irrelevant if
      color writes are disabled (via ColorMask).


I would actually mess around and try some different fragment programs to make sure your code works. For example, you could draw every pixel red and check your color buffer to make sure it's doing the right thing.
Aldous11
Gnoblar
 
Posts: 1
Kudos: 0
Joined: 16 Sep 2010


Return to Help

Who is online

Users browsing this forum: Google [Bot] and 7 guests