# Help needed binding textures on AMD cards

**URL:** https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098
**Category:** Using Cinder
**Created:** [March 20, 2018, 10:40am UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098 "2018-03-20T10:40:35Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![ISB](https://avatars.discourse-cdn.com/v4/letter/i/9dc877/32.png) [@ISB](https://discourse.libcinder.org/u/ISB)
#### Post date: [March 20, 2018, 10:40am UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098/1 "2018-03-20T10:40:35Z")

</div>

Hi,  
I’ve recently noticed some unknown behaviour on an AMD Card. Previously I’ve been using nvidia cards & everythings worked absolutely fine, but having swapped to an AMD Radeon R9 270x (latest catalyst drivers), I’ve been having nothing but trouble.

The current thing that’s proving difficult is binding multiple textures to a shader. On nvidia this has been working perfectly for me in an app, but now I can’t seem to get it to respect the binds. I’ve distilled it to a super basic working app case, and still no luck;  
Cinder Test App:

```
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class MultiBindApp : public App {
  public:
	void setup() override;
	void update() override;
	void draw() override;
	void LoadShaders();
	gl::GlslProgRef Multibind;
	gl::Texture2dRef TexA;
	gl::Texture2dRef TexB;

};

void MultiBindApp::LoadShaders() {
	Multibind = gl::GlslProg::create(loadAsset("mbind.vert"), loadAsset("mBind.frag"));

}

void MultiBindApp::setup()
{
	TexA = gl::Texture2d::create(loadImage(getAssetPath("ImageA.png")));
	TexB = gl::Texture2d::create(loadImage(getAssetPath("ImageB.png")));
	LoadShaders();
}
	
void MultiBindApp::update()
{
	LoadShaders();
}

void MultiBindApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) ); 

	Multibind->bind();

		TexA->bind(3);
		Multibind->uniform("TextureA", 3 );
		TexB->bind(4);
		Multibind->uniform("TextureB", 4);

	gl::drawSolidRect(Rectf(0.0, 0.0, 128.0, 128.0));
	TexA->unbind();
	TexB->unbind();
}

void prepareSettings(App::Settings *settings) {
	settings->setConsoleWindowEnabled(true);
}

CINDER_APP( MultiBindApp, RendererGl, prepareSettings)

```

Fragment shader:

```
#version 150
uniform sampler2D TextureA;
uniform sampler2D TextureB;
in vec2 TexCoord;

out vec4 oColor;

void main( void )
{
	oColor.xyz = texture( TextureA,TexCoord).xyz;
}	

```

No matter what I do, the best I get shown is the last bound texture. So if I bind TexA & then TexB, my shader will only ever show TexB (no matter if I put texture(TextureA…); etc.)

I’ve experimented with different bind methods too - using bind() & then sending TexA-\>getId() as the uniform index instead, which returns blank.

I’m not really sure what else to try - I was hoping a test case app would highlight where I was going wrong, but instead it’s confused me further. I’m hoping there’s a standard path to this that I’m missing.  
I get similar issues in the \_opengl samples too - the normal mapping adv. sample seems affected.

Any help is greatly appreciated, I’m completely stuck!

---

<div class="post-metadata">

### Author: ![felixfaire](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/felixfaire/32/168_2.png) [@felixfaire](https://discourse.libcinder.org/u/felixfaire)
#### Post date: [March 20, 2018, 11:02am UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098/2 "2018-03-20T11:02:49Z")

</div>

Could it be that your shader is only sampling one texture? Its probably something to do with the driver trying to match the bound textures to the shader samplers, but if you dont use TextureB in the shader the driver will just remove the uniform as it isnt being used.

you could also try something like this in your draw function (Scoped state variables generally reduce complexity)

```
ScopedGlslProg glslScp(Multibind);
ScopedTextureBind tex0Scp(TexA, 0);
ScopedTextureBind tex0Scp(TexB, 1);
Multibind->uniform("TextureA", 0);
Multibind->uniform("TextureB", 1);

gl::drawSolidRect(Rectf(0.0, 0.0, 128.0, 128.0));

```

And something like this in your shader to see if both textures are bound

```
vec4 colA = texture( TextureA, TexCoord );
vec4 colB = texture( TextureB, TexCoord );
oColor = colA + colB;
```

---

<div class="post-metadata">

### Author: ![ISB](https://avatars.discourse-cdn.com/v4/letter/i/9dc877/32.png) [@ISB](https://discourse.libcinder.org/u/ISB)
#### Post date: [March 20, 2018, 11:25am UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098/3 "2018-03-20T11:25:33Z")

</div>

> [@felixfaire](#):
>
> ScopedGlslProg glslScp(Multibind);  
> ScopedTextureBind tex0Scp(TexA, 0);  
> ScopedTextureBind tex0Scp(TexB, 1);  
> Multibind-\>uniform(“TextureA”, 0);  
> Multibind-\>uniform(“TextureB”, 1);

Perfect - seems to work. I did have to make sure the shader was consuming the two textures. Bizarrely, I’ve just tried my first post code on an nvidia machine where the results are fine, but I now suspect this to may just be leniency on behalf of those drivers & not the best case. Definitely learning a lesson to test across many devices right now!

I have until now stayed away a little from scoped binds for this - as I need to wrap them in a conditional in my situation -

```
if( thisothertex ) {
thisothertex->bind();
shader->uniform("", etc etc);
}

```

Where the shader always consumes the tex sample anyway. ofc with the conditional, they are always going to go out of scope.  
However typing that out suggests I may be just as well to conditionally bind a dummy sample as a fallback; it makes no sense to rely on unknown behaviour. As you point out, scoping it definitely reduces complexity & works, so I will go down this path.

Perfect, thank you!

---

<div class="post-metadata">

### Author: ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)
#### Post date: [March 20, 2018, 2:02pm UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098/4 "2018-03-20T14:02:48Z")

</div>

AMD drivers are more strict in their support for OpenGL, so usually if it works on AMD it also works on NVIDIA but not the other way around.

Good to hear it’s working now. A few things I would have suggested is to make sure textures are enabled (in Cinder, prior to v0.9, you had to call `enableAndBind()` at least once). The other suggestion would have been to make sure the shader writes to the `oColor.a` component as well. In general, it would be smart to add a try-catch block to `LoadShaders` to catch any shader compilation errors.

A suggestion of a different nature would be to prefix your variable names with `m` for member variables, which is what most C++ programmers do nowadays, but that is a matter of preference I guess.

-Paul

---

<div class="post-metadata">

### Author: ![ISB](https://avatars.discourse-cdn.com/v4/letter/i/9dc877/32.png) [@ISB](https://discourse.libcinder.org/u/ISB)
#### Post date: [March 20, 2018, 4:53pm UTC](https://discourse.libcinder.org/t/help-needed-binding-textures-on-amd-cards/1098/5 "2018-03-20T16:53:05Z")

</div>

Great stuff, thank you for the info! Good to hear about AMD being much stricter - definitely matches up with what I’ve been finding. I’ve already patched up a few shader compile issues I was hitting. I think I’ll try and stick to AMD as a main development config.

@felixfaire Just popping back in to say thanks again - just trying this out in the wild & it’s definitely solved my issues. I’ve used scoped texture binds now, and handled the failures with a default texture.
