[2.2] 'sampler' not detected as a named constant in HLSL pixel shader

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
kaboissonneault
Gnoblar
Posts: 9
Joined: Fri Aug 14, 2020 10:41 pm

[2.2] 'sampler' not detected as a named constant in HLSL pixel shader

Post by kaboissonneault »

I was working on a Dear ImGui renderer for Ogre 2.2. The implementation is mostly based on this 2.1 implementation (https://bitbucket.org/ChaosCreator/imgu ... anager.cpp) and the "official" Ogre 1 renderer, but using the Ogre 2.2 textures and structured to my preferences.

The Direct3d11 pixel shader used by Dear ImGui is usually this:

Code: Select all

struct PS_INPUT
{
	float4 pos : SV_POSITION;
	float4 col : COLOR0;
	float2 uv  : TEXCOORD0;
};
sampler sampler0;
Texture2D texture0;
		
float4 main(PS_INPUT input) : SV_Target
{
	float4 out_col = input.col * texture0.Sample(sampler0, input.uv);
	return out_col;
}
The 2.1 implementation used the following line to set the "sampler0" value

Code: Select all

material->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("sampler0", 0);
So I assume this used to be supported in Ogre 2.1

However, when I do the same in Ogre 2.2, it says no such named constants exist. If I leave the variable unset, I get
The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound
as an error on the next draw call.

Does anyone know if this is a regression in Ogre 2.2, or if there's simply a new way to set this value?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.2] 'sampler' not detected as a named constant in HLSL pixel shader

Post by dark_sylinc »

Ogre 2.1+ does not collect texture (maybe it does?) nor sampler uniforms to set them from C++; except for OpenGL.

You need to embed the register in HLSL syntax, e.g.

sampler sampler0 : register( s0 );
Texture2D texture0 : register( t0 );

If the register is not explicitly set, HLSL compiler will assign a default one
kaboissonneault
Gnoblar
Posts: 9
Joined: Fri Aug 14, 2020 10:41 pm

Re: [2.2] 'sampler' not detected as a named constant in HLSL pixel shader

Post by kaboissonneault »

Alright, I've updated my shader as you suggested. However, sorry, but it's not obvious to me what I should do now that my sampler is a register. The rendering still fails because of the unset sampler at slot 0, and I can't set it through named constants.

Just to be clear, the full message is
D3D11 device cannot draw indexed
Error Description:ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults.

Active OGRE shaders:
VS = imgui/VP/D3D11
FS = imgui/FP/D3D11
The message seems to hint that it's not actually an error (just an info), but Ogre will still throw an "ERR_RENDERINGAPI_ERROR" exception. Perhaps there is something that can be done to ignore this?
kaboissonneault
Gnoblar
Posts: 9
Joined: Fri Aug 14, 2020 10:41 pm

Re: [2.2] 'sampler' not detected as a named constant in HLSL pixel shader

Post by kaboissonneault »

Alright, I've added

Code: Select all

renderSystem->_setHlmsSamplerblock(0, hlmsManager->getSamplerblock(Ogre::HlmsSamplerblock()));
and the rendering does not complain about having not samplers set at slot 0
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.2] 'sampler' not detected as a named constant in HLSL pixel shader

Post by dark_sylinc »

kaboissonneault wrote: Tue Sep 01, 2020 9:34 pm Alright, I've added

Code: Select all

renderSystem->_setHlmsSamplerblock(0, hlmsManager->getSamplerblock(Ogre::HlmsSamplerblock()));
and the rendering does not complain about having not samplers set at slot 0
Yes, if you're doing low level direct rendering that's the correct solution but there is one gotcha with your current version:
hlmsManager->getSamplerblock( ... ) will return a reference counted pointer.

If you keep doing that, you're leaking samplerblocks until the reference count overflows.

Code: Select all

HlmsSamplerblock *samplerblock = hlmsManager->getSamplerblock(Ogre::HlmsSamplerblock());
renderSystem->_setHlmsSamplerblock(0, samplerblock);

//After you're done using it
hlmsManager->destroySamplerblock( samplerblock );
For best performance you should keep the samplerblock around until it's no longer needed, rather than retrieving and destroying it every frame.
Post Reply