can't output DEPTH in a fragment program

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
Thieum
Gnome
Posts: 342
Joined: Wed Apr 26, 2006 5:13 pm
Location: Bordeaux, France
Contact:

can't output DEPTH in a fragment program

Post by 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 ?
0 x

User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19261
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
Contact:

Post by 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.
0 x

User avatar
Thieum
Gnome
Posts: 342
Joined: Wed Apr 26, 2006 5:13 pm
Location: Bordeaux, France
Contact:

Post by 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.
0 x

User avatar
iloseall
Gremlin
Posts: 156
Joined: Sun Sep 14, 2003 3:54 am
Location: Beijing China
Contact:

Post by iloseall » Thu Mar 06, 2008 12:43 pm

Maybe you has two files named "TerrainDecal2.cg".
Try to search TerrainDecal2.cg.
0 x

User avatar
Thieum
Gnome
Posts: 342
Joined: Wed Apr 26, 2006 5:13 pm
Location: Bordeaux, France
Contact:

Post by 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.
0 x

Caelin
Gnoblar
Posts: 5
Joined: Sun Apr 20, 2008 10:04 am

Post by 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
0 x

Caelin
Gnoblar
Posts: 5
Joined: Sun Apr 20, 2008 10:04 am

Post by 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
0 x

User avatar
Thieum
Gnome
Posts: 342
Joined: Wed Apr 26, 2006 5:13 pm
Location: Bordeaux, France
Contact:

Post by Thieum » Mon Apr 28, 2008 8:41 am

Thanks for the answer!
0 x

User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
Contact:

Post by _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?
0 x
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games

Caelin
Gnoblar
Posts: 5
Joined: Sun Apr 20, 2008 10:04 am

Post by 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);
}
0 x

Aldous11
Gnoblar
Posts: 1
Joined: Thu Sep 16, 2010 5:41 am

Re: can't output DEPTH in a fragment program

Post by 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.
0 x

Post Reply