OpenGL to DirectX. Constant buffers.

Started by
3 comments, last by ongamex92 9 years, 9 months ago

Hi.

Im busy creating a directX11 renderer for my game. I did the neccesary refactoring to seperate the graphics calls from the rest of the engine by creating an interface and moving all the opengl code into an implementation of the interface. Then i created a directx implementation of the interface and started implementing it bit by bit. Now I pretty much have most of it down except for constant buffers.

The interface very much caters towards opengl since thats the first implementation i wrote (and before now I didnt know any directX). As a result the directX implementation looks more like opengl emulation than a proper directx implementation. But thats fine for now. Once i get the game fully rendered in directX il start looking at ways to improve that.

So now my implementation has a method named. sendUniform1i (string uniformName, int value) wich would in the opengl implemenation of course set the int uniform named 'uniformName' to the value in 'value' for the current shaders. Im strugling to figure out how i would implement (emulate?) this in directx. Remember this is just my intermediate step i dont care how dirty it is for now. I was thinking along the lines of giving each constant variable in directx its own constant buffer but as far as i can tel the only way to reference this buffer in code would be by its 'buffer slot number' (: register(b0) etc). Whereas i need a way to get a handle on it by its name. The constant buffer as declared in a shader does have a name but i cant seem to find any example of how you can use that name. I might just be mssing it.

Any suggestions?

thnx in Advance

Advertisement
I hear the modern way of OpenGL looks the same, i.e. instead of uniforms you got something similar (uniform buffer objects IIRC). So no, don't give every variable a different constant buffer otherwise you will run out of slots at one point for sure. Rather group by update frequency (per frame, per object, etc.)

What you have in mind is/was available as convenience and is called an effect framework. It was part of the old SDK (June 2010), namely the D3DX library. The recent SDKs were stripped thereof but you can get replacements for almost everything as open source libraries (DirectXTK et.al). The effect library is here.

If you want to roll your own, you can get any information from a compiled shader (slot number, variable byte offset, type etc.) with the shader reflection system (D3DReflect).

Yes i stil use some pretty old opengl I supose I will first refactor my existing code into using uniform buffer objects before continueing with the directX implementation.

Thnx!

Just for clarification:


..as far as i can tel the only way to reference this buffer in code would be by its 'buffer slot number' (: register(b0) etc)..

By buffer slot number - true. Register number - maybe, maybe not. Whether the register numbers line up with the slot numbers depends on a couple things, so, as a suggestion, don't associate register numbers and slot numbers in your mind.

If you use an effect framework as unbird suggests, you don't need to worry about register numbers anyway.

I really don't want to confuse you if you're not fully into D3D11 yet. So read further only at your peril.

If you eventually compile shaders separately (e.g., a vertex shader, a geometry shader and a pixel shader) from the same file, the slot numbers associated with a particular buffer are by shader usage, not register number.

E.g., if you have a file written in HLSL which includes, for instance, both vertex shader and a pixel shader code, and you compile that file 2 times (once for each shader), the slots for any constant buffers will depend on whether the buffer is used by a particular shader, whatever the register number. Other buffers not needed by the shader will not be compiled with it.

For example:


// shader file
buffer VS_stuff
{
  float4 someVariable; // not used by the pixel shader
};

buffer PS_stuff
{
  float4 someOtherVariable; // not used by the vertex shader
};

... VS and PS code

In your rendering code:


context->VSSetConstantBuffers( 0, 1, (..resource reflecting VS_stuff)); // slot 0
context->PSSetConstantBuffers( 0, 1, (..resource reflecting PS_stuff)); // ALSO slot 0

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

If it is urgent and you don't need the performance gain from cbuffers, you can still use them in the old fasion way(aka. you can fake separate uniform binding)

in HLSL

Declare your uniforms as global scope variable, they will be part of the implicitly created constant buffer .

When you Call D3DReflect this function will return the layout of the created cbuffer, its bind slot(should be always the same in that specific case) ect.

Create one large enough cbuffer for each shader type. This so all vertex shaders will use that cbuffer and so on for each shader type. When you call your function that updates the uniforms you will update the cbuffer storage behind the scenes.

Also you will have to merge the uniform names and the buffers because in OGL you bind uniforms per program in d3d you bind uniforms per shader stage.

Another thing that will cause you headaches is the sampler and texture binding!

Hope that will help

EDIT:


Another thing that will cause you headaches is the sampler and texture binding!

I've actually cheated here. http://www.opengl.org/wiki/GLAPI/glBindSampler

There are sampler state objects in OGL

This topic is closed to new replies.

Advertisement