views:

375

answers:

3

I was wondering, if I render a scene using a shader to which I pass in a texture that also happens to be the render target for that scene will it cause any unwanted behaviour?

So basically:

texture t;

shader->SetTexture("texture",t);

device->SetRenderTarget( 0, t->surface );

shader->Begin("effect")
// do some more shader stuff

device->EndScene();

what will this cause exactly?

If I don't clear the render target before rendering will the texture still work all the same? I just assume the final changes don't get written into the texture until device->End is called?

+2  A: 

Though I can't point out specifics, I'm pretty sure it's undefined behavior. The method a graphics card uses for shading fragments can vary (do different amounts at a time, etc), but in any practical case, it does more than one fragment at a time. This means you'll be both reading and writing to the same locations, causing race conditions. I don't think it's recommended.

GMan
+2  A: 

I assume you're talking about DirectX9. The documentation does not say anything about this specific case, but I can tell you the following:

I just assume the final changes don't get written into the texture until device->End is called

This is a wrong assumption. Think about it, you're assuming all the pixels of all the triangles you draw will be stored 'somewhere' and all your texture fetches executed without any pixels being written back to the render target. This requires an arbitrary amount of memory and is therefore not possible.

In practice:

  • the hardware usually processes triangles as they come, many at once
  • it updates the frame buffer (which in your case is the texture memory backing) when it wants, assuming there can't be race conditions

So, assuming DX9 does not complain (try it if you really want to know, I don't do DX9 anymore), it will be undefined.

That said, DirectX10 is being more explicit about it (source):

If any subresources are also currently bound for reading or writing (perhaps in a different part of the pipeline), those bind points will be NULL'ed out to prevent the same subresource from being read and written simultaneously in a single rendering operation.

So, in DirectX10, your texture setting will be removed by the API.

Bahbar
+1  A: 

The debug runtime will prevent you doing this and provide a warning. The release runtime "might" (but probably won't) work.

The problem comes form the fact that there is quite a delay between loading the pixel from a texture and it being used. This is fixed by loading a block of texels into a cache. The writes are buffered and written straight to memory. Thus you will likely end up with a problem that may be reading a texel that may already have been updated but the cache will be out of date. If you are ONLY reading the texel that is being written to it "may" work but realistically such implementation details are left to the IHVs. They are under no obligation to allow this to work.

As said by others ... it is very much undefined behaviour.

Goz