Sign in to follow this  
Pyrogame

DX11 [Solved] DX11 (SlimDX) - Multithreaded rendering setShaderValue problem

Recommended Posts

First of all, I'm using SlimDX in C#. I'm rendering (or trying to ^^) my new awesome game (6 quads â 4 vertices!) in a few threads. I do this this way (pseudo-code):
foreach(m as material) {
  shader.setResource(m);
  foreach(i as indexbuffer[material]) {
     deferredContext.renderIndexed(i);
  }
}
Then I render this in an other thread by creating the command list from the deferred context and executing this on the immediate context. It renders well. But maybe, you see my problem already: Because the call "setResource" on the shader is not deferred, if the immediate context executes the command list, it uses the last state of the shader (ofcourse). How I can manage this? Is there something ready I can use? Or had the DX team forget to add this feature to their cool new DX11? ^^ [Edited by - Pyrogame on February 9, 2010 5:27:35 PM]

Share this post


Link to post
Share on other sites
In D3D11 you set shader resources using the device context (DeviceContext.PixelShader.SetShaderResource in SlimDX). So if you're using a deferred context, the setting of the resource is deferred and the state change could happen in the right order.

What is "shader.setResource" doing?

Share this post


Link to post
Share on other sites
"shader.setResource" is doing this:

effectVariable.AsResource().SetResource((ShaderResourceView)value);


I have an effect file (.fx) wich contains some global values, for example the view matrix. Then I set a value by its name (vMatrix = myMatrix). I do not know (or I want not to pay attention), which shader uses this value. Is there something deferred I can use for the whole effect? Or may I set the value for all shaders? Or can I investigate, which shaders need the value? Or is the way of using effects in Dx11 the wrong one and I have to separate the whole shaders in my C# code?

And if I have to set the values for each shader separately, then the method "SetShaderResource()" needs a slot number. What is that? Have I to count the number of each value, or something like this?

Share this post


Link to post
Share on other sites
Hmmm...I'm not sure how Effects11 handles deferred contexts. I would think that this would be a case they handle, but I'd have to check through the docs and maybe the source code.

EDIT: Looking through the docs, it looks like an Effect just keeps all of its state internally and then applies it to a particular device context when you call Apply().

Quote:
Original post by Pyrogame
And if I have to set the values for each shader separately, then the method "SetShaderResource()" needs a slot number. What is that? Have I to count the number of each value, or something like this?


Textures, buffers, and samplers and mapped to specific registers in a particular shader. The index of that register specifies what slot you would need to pass to SetShaderResource. Typically when you don't use the effects framework you manually assign the register, so that you know which slot you have to pass. If you do use the effects framework, it handles the mapping register mapping for you so that you don't have to worry about it.

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
EDIT: Looking through the docs, it looks like an Effect just keeps all of its state internally and then applies it to a particular device context when you call Apply().


Yes, but this is the core problem. I do not known, how I can set the state of an Effect in a deferred context. The problem is:

1) Set Effect A variable p to 1,0,0.
2) Effect.Apply(deferredContext)
3) render(deferredContext)
4) Set Effect A variable p to 0,1,0.
5) Effect.Apply(deferredContext)
6) render(deferredContext)
7) deferredContext.getCommandList().execute(immediateContext)

On step 7, the effects variable p is set to 0,1,0. The command list calls then:
1) Effect.Apply(immediateContext)
2) render(deferredContext)
3) Effect.Apply(immediateContext)
4) render(deferredContext)

It does not set the effect variable p to 1,0,0 before executing the first apply, because this assignment to the effect is not stored on the deferred context.

I think, if we couldn't get this working, that this may be a big design isue on the DX11-Framework. But I can't imagine, that the DX-DevTeam had forget such big thing. There must be something, I can do. The last thing I want to do, is, to create my own command list (list of delegates), and then call to execute it in the same way I'm calling the deferredContext command list execution.

Quote:
Original post by MJP
Textures, buffers, and samplers and mapped to specific registers in a particular shader. The index of that register specifies what slot you would need to pass to SetShaderResource. Typically when you don't use the effects framework you manually assign the register, so that you know which slot you have to pass. If you do use the effects framework, it handles the mapping register mapping for you so that you don't have to worry about it.

Thank you for that info. But how I can distribute the registers on my resources? Every resource needs a separate register? Are there some types of registers or are they unified?... But you will understand me, if I say: no no no, I want to use the effect framework, which should be the solution for exactly this problem of managing registers etc. :)

Share this post


Link to post
Share on other sites
I think you need a copy of the Effect for each thread/deferred context. AIUI from the documentation you should create the Effect and then use its Clone method to create a copy for each deferred context that you have (which should be one per thread).

That way they'll all share the same actual shaders but will have unique register state. Then when you call Apply on the effect you pass in the deferred context. So you end up with something like:

[Thread1]
1) Set ClonedEffect A variable p to 1,0,0.
2) ClonedEffect.Apply(deferredContext)
3) render(deferredContext)
4) Set ClonedEffect A variable p to 0,1,0.
5) ClonedEffect.Apply(deferredContext)
6) render(deferredContext)
7) deferredContext.getCommandList()

[Thread2]
1) OrigEffect.Apply(immediateContext)
2) render(immediateContext)
3) OrigEffect.Apply(immediateContext)
4) render(immediateContext)

Somewhere in that lot you need the immediateContext to execute the command list from the deferredContext (preferrably in Thread2). What you had with

deferredContext.getCommandList().execute(immediateContext)

and

3) Effect.Apply(immediateContext)
4) render(deferredContext)

doesn't make much sense unless you've got some method of stopping the execution from stomping all over the immediateContexts state - I mean what would happen if thread2 did step 1, then at that point thread2 did your step 7 execute and made state changes to the immediateContext that then affect thread2's step 2...

You'd probably be better of with:

[Thread1]
... Generate command list
send to thread3

[Thread2]
... Generate command list
send to thread3

[Thread3]
immediateContext.Execute(first_recieved_list)
immediateContext.Execute(next_recieved_list)

Thats my understanding anyway - I've not got to that point yet so I may be wrong! :)

[Edited by - hornet1990 on February 9, 2010 2:02:17 PM]

Share this post


Link to post
Share on other sites
Indeed I believe that what hornet suggests is the intended way to handle effects across different device contexts. This way you're not modifying state in one thread that's shared in another.

Quote:
Original post by Pyrogame
Thank you for that info. But how I can distribute the registers on my resources? Every resource needs a separate register? Are there some types of registers or are they unified?... But you will understand me, if I say: no no no, I want to use the effect framework, which should be the solution for exactly this problem of managing registers etc. :)


You can find the low-level documentations for these things here, including a list of the registers I'm talking about. Unfortunately it's a little patchy and you have to look through a few sections to find out what the registers are for, so I'll give you a quick list:

r# - temporary registers - used for storing operands and results of math ops
x# - indexable temp. registers - same as above, except you can index into them using the value of an r# register
v# - vertex inputs - you map your vertex input streams to these registers
t# - resource registers - you map your texture resources to these registers
s# - sampler registers - you map your sampler states to these registers, and then specify one of these when you want to sample a texture resource
cb# - constant buffer registers - you map your constant buffers to these
icb# - immediate constant buffer register - you assign "hard-coded" values to this constant buffer, instead of mapping a buffer in your app

For any single shader you would just need to make sure than any particular register is only mapped once. So if you had two textures, you would probably just assign them to t0 and t1. A different shader could then use t0 and t1 afterwards.

I wasn't suggesting that you shouldn't use the effect framework...for anything non-trivial you'll definitely want to have a wrapper over the low-level stuff so that you don't have to explicitly manage registers and slot numbers. I was just trying to help you understand what's going on under the hood, because it's useful knowledge for when you're debugging problems like the one you're having.

Share this post


Link to post
Share on other sites
Thank you for your comments :) I've found the problem.

@hornet1990:
Yes, I do it like you posted it on your last passage, except that I do not send the command lists to a 3rd thread. I render simultaneously on every cpu-core, and on the end I create the command list from what I rendered (on the same thread), and render this on the real device using the immediate context. This way, all threads can render parallel, but on the end all have to use the hardware, so only one thread can execute at time. I always have to wait, until all rendering threads are ready, so this might be the right thing I do (I think so ^^).

@MJP
You are the best! I had called the apply method, but only once per pass on the begining. But I have to call this after a change to the shader state ofcourse (like setting the texture) and before the render() method.

Problem solved. Thank you very much for your help, both of you! Sorry for bother you with this "bug" of my own.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      628290
    • Total Posts
      2981858
  • Similar Content

    • By GreenGodDiary
      I'm attempting to implement some basic post-processing in my "engine" and the HLSL part of the Compute Shader and such I think I've understood, however I'm at a loss at how to actually get/use it's output for rendering to the screen.
      Assume I'm doing something to a UAV in my CS:
      RWTexture2D<float4> InputOutputMap : register(u0); I want that texture to essentially "be" the backbuffer.
       
      I'm pretty certain I'm doing something wrong when I create the views (what I think I'm doing is having the backbuffer be bound as render target aswell as UAV and then using it in my CS):
       
      DXGI_SWAP_CHAIN_DESC scd; ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); scd.BufferCount = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_UNORDERED_ACCESS; scd.OutputWindow = wndHandle; scd.SampleDesc.Count = 1; scd.Windowed = TRUE; HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &gSwapChain, &gDevice, NULL, &gDeviceContext); // get the address of the back buffer ID3D11Texture2D* pBackBuffer = nullptr; gSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // use the back buffer address to create the render target gDevice->CreateRenderTargetView(pBackBuffer, NULL, &gBackbufferRTV); // set the render target as the back buffer CreateDepthStencilBuffer(); gDeviceContext->OMSetRenderTargets(1, &gBackbufferRTV, depthStencilView); //UAV for compute shader D3D11_UNORDERED_ACCESS_VIEW_DESC uavd; ZeroMemory(&uavd, sizeof(uavd)); uavd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; uavd.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; uavd.Texture2D.MipSlice = 1; gDevice->CreateUnorderedAccessView(pBackBuffer, &uavd, &gUAV); pBackBuffer->Release();  
      After I render the scene, I dispatch like this:
      gDeviceContext->OMSetRenderTargets(0, NULL, NULL); m_vShaders["cs1"]->Bind(); gDeviceContext->CSSetUnorderedAccessViews(0, 1, &gUAV, 0); gDeviceContext->Dispatch(32, 24, 0); //hard coded ID3D11UnorderedAccessView* nullview = { nullptr }; gDeviceContext->CSSetUnorderedAccessViews(0, 1, &nullview, 0); gDeviceContext->OMSetRenderTargets(1, &gBackbufferRTV, depthStencilView); gSwapChain->Present(0, 0); Worth noting is the scene is rendered as usual, but I dont get any results from the CS (simple gaussian blur)
      I'm sure it's something fairly basic I'm doing wrong, perhaps my understanding of render targets / views / what have you is just completely wrong and my approach just makes no sense.

      If someone with more experience could point me in the right direction I would really appreciate it!

      On a side note, I'd really like to learn more about this kind of stuff. I can really see the potential of the CS aswell as rendering to textures and using them for whatever in the engine so I would love it if you know some good resources I can read about this!

      Thank you <3
       
      P.S I excluded the .hlsl since I cant imagine that being the issue, but if you think you need it to help me just ask

      P:P:S. As you can see this is my first post however I do have another account, but I can't log in with it because gamedev.net just keeps asking me to accept terms and then logs me out when I do over and over
    • By noodleBowl
      I was wondering if anyone could explain the depth buffer and the depth stencil state comparison function to me as I'm a little confused
      So I have set up a depth stencil state where the DepthFunc is set to D3D11_COMPARISON_LESS, but what am I actually comparing here? What is actually written to the buffer, the pixel that should show up in the front?
      I have these 2 quad faces, a Red Face and a Blue Face. The Blue Face is further away from the Viewer with a Z index value of -100.0f. Where the Red Face is close to the Viewer with a Z index value of 0.0f.
      When DepthFunc is set to D3D11_COMPARISON_LESS the Red Face shows up in front of the Blue Face like it should based on the Z index values. BUT if I change the DepthFunc to D3D11_COMPARISON_LESS_EQUAL the Blue Face shows in front of the Red Face. Which does not make sense to me, I would think that when the function is set to D3D11_COMPARISON_LESS_EQUAL the Red Face would still show up in front of the Blue Face as the Z index for the Red Face is still closer to the viewer
      Am I thinking of this comparison function all wrong?
      Vertex data just in case
      //Vertex date that make up the 2 faces Vertex verts[] = { //Red face Vertex(Vector4(0.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(0.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(0.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), //Blue face Vertex(Vector4(0.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(0.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(0.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), };  
    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By turanszkij
      If I do a buffer update with MAP_NO_OVERWRITE or MAP_DISCARD, can I just write to the buffer after I called Unmap() on the buffer? It seems to work fine for me (Nvidia driver), but is it actually legal to do so? I have a graphics device wrapper and I don't want to expose Map/Unmap, but just have a function like void* AllocateFromRingBuffer(GPUBuffer* buffer, uint size, uint& offset); This function would just call Map on the buffer, then Unmap immediately and then return the address of the buffer. It usually does a MAP_NO_OVERWRITE, but sometimes it is a WRITE_DISCARD (when the buffer wraps around). Previously I have been using it so that the function expected the data upfront and would copy to the buffer between Map/Unmap, but now I want to extend functionality of it so that it would just return an address to write to.
    • By mister345
      Trying to write a multitexturing shader in DirectX11 - 3 textures work fine, but adding 4th gets sampled as black!
      Could you please look at the textureClass.cpp line 79? - I'm guess its D3D11_TEXTURE2D_DESC settings are wrong, 
      but no idea how to set it up right. I tried changing ArraySize from 1 to 4, but does nothing. If thats not the issue, please look
      at the LightShader_ps - maybe doing something wrong there? Otherwise, no idea.
          // Setup the description of the texture.
          textureDesc.Height = height;
          textureDesc.Width = width;
          textureDesc.MipLevels = 0;
          textureDesc.ArraySize = 1;
          textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
          textureDesc.SampleDesc.Count = 1;
          textureDesc.SampleDesc.Quality = 0;
          textureDesc.Usage = D3D11_USAGE_DEFAULT;
          textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
          textureDesc.CPUAccessFlags = 0;
          textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
      Please help, thanks.
      https://github.com/mister51213/DirectX11Engine/blob/master/DirectX11Engine/Texture.cpp
       
  • Popular Now