... #1, #2 and #3 ...
Interesting stuff.
My take on those 3 designs...
#1 could be viewed as a closure/partial-application of the device into the Bind() call, in a sense the Texture class is just a closure type. The DrawThing function should know that if it accepts closure types as its arguments then it doesn't get to dictate the closed environment. Either it should not have accepted closure types or it needs a way to assert a pre-condition that the two textures refer to the same device.
#2 makes me feel much more uncomfortable that #3, but I would have a hard time saying exactly why. Maybe it's just a matter of convention. Like Krohm, I would feel somewhat entitled to construct with one device and bind to another - until reading the documentation.
#3 technically suffers the same problem as #2 but follows a more familiar convention so I think it really is better than #2. It also exposes an underlying truth that the device acts like a factory for textures, whereas I think #2 kind of gives the impression that a device is merely a component of a texture.
Designs #2 and #3 try to pretend that a texture is a stand-alone object and that it can be separated from the device at one point (at creation) and re-join with it later on (at bind-time). This is almost true and close-enough that it can be implemented that way provided there are sufficient runtime checks at the re-join point.
Design #1 never lets the device separate from the texture, so the only thing it does is try to present a texture as a stand-alone object.
Textures being stand-alone raises the question of whether a texture might be able to out-live the device.
#2 and #3 don't really deal with that too well - the destruction of the device object may put the texture objects into a weird state (another example of spooky action at a distance).
Design #1 could deal with that if it used a shared_ptr to reference the device which guarantees that the lifetime of the device is at least as long as the texture's.
I usually think all of this comes down to limitations in the language itself, that you have to enforce this kind of thing yourself and there aren't great ways to describe the relationships to the compiler or to the runtime environment.
Other areas of the language have the same problem, for example you wouldn't expect to be able to use an iterator in a different container to the one that created it, or to use an iterator after the container has been destructed.
Maybe using handles (like integer handles) rather than objects would side-step some of those issues.