I have an HLSL shader that defines some resources, say a constant buffer:
cbuffer MyCB : register(b0);
If I compile my shader, I will then be able to query the register through the reflection API. But is it possible to change the register (for instance, to b3) in a compiled shader blob in a similar manner you can assign bind points to resources in a compiled OpenGL program?
There is no API to change the shader bindings at runtime in a compiled shader.
If you jumped through many hoops, you might be able to achieve this with dynamic shader linking in Shader Model 5.0, although it would be lots of work and not really worth it, when there is a very easy alternative - simply create a new compiled shader with the bindings you want.
You can accomplish this in direct3d12 by specifying a BaseShaderRegister other than zero, or using different RegisterSpace values, in the D3D12_DESCRIPTOR_RANGE struct. If code changes are not feasible, you can isolate each set of registers implicitly by setting the root parameter's ShaderVisibility property. This will isolate, for example, VS b0 from PS b0. For more details, you can check out the developer video on the topic.
The only time you will run into trouble is if you've actually explicitly bound two resources to the same slot and register space (by explicitly specifying it using shader model 5.1 syntax). In this case, you are expected to understand that in D3D12, registers are shared cross-stage, and it's up to you to make sure you have no collisions.
In D3D11, this problem does not occur as each stage has its own register space (VS b0 is not the same as PS b0) and you can't share even if you wanted to. Still, if you for some reason have a component hard-coded to attach data to VS b0 but your vertex shader has already been compiled to expect it at b1, there's not much you can do.
Related
I'm working on my own D3D12 wrapper, and I'm in the beginning 'schema' phase.
I understand the purpose of the PSO in a very simple rendering pipeline, but say I've multiple objects, meshes, models, whatever terminology works best, and I would like to use a different pixel shader for each,
for clarification, I would make multiple PSOs for each of these objects correct?
Sorry for the simple question, it's just a clarification I really need, thank you.
You need a distinct Pipeline State Object for every unique combination of all states:
VS, PS, GS, etc. Shader Objects
Blend, Depth, and Raster state
Render Target format
Number of render targets (MRT vs. 1)
Sample count (MSAA vs. not)
In practice that means at least one PSO per unique material in your entire scene.
I have opengl code that uses the fixed pipeline.
Hitting two birds with one stone, I need a wrapper that can help me with the following tasks:
Convert the code to the new shader-based pipeline with minimal effort.
I have a class that calls opengl functions, such as: glBegin(triangles/lines), glVertex, glPushMatrix, glTranslate, glColor, gluSphere.
Ideally, I'd like it to derive from a class that supplies these functions in the base class. Behind the scenes, it would use the same high level logic as the fixed pipeline.
I'd like to export an opengl scene to .collada to load in an external renderer.
Opengl is low level rendering, and it doesn't have the concept of a scene. For example, this reddit post:
"You realize that you have to write a shim to capture all API calls
you are interested in to do that. Then, when finally, a draw call is
emitted you have to parse every single vertex and collect the data
from all over the memory from the buffers that you have recorded from
the APi calls that set up VAOs, VBOs and IBOs. Then you have to parse
the shader source code so that you can see which uniforms and vertex
attributes contribute to vertex clip coordinate generation. Then you
also have to synthesize/guess which outputs are normal, color, texture
coordinate and so on from the shader source if the resulting program
even have those in .obj file format-wise.
This gets even more complicated if Compute is used to generate data
inside the GPU for any of the buffers. If geometry or tessellator is
used then you also have to implement one of those so that you get
accurate outputs from the vertex processing. TL;DR - you have to write
your own OpenGL 4.5 driver that does exactly the same things a real
hardware driver would do. Good luck with that."
However, my scene is simple, using the fixed pipeline operations above.
I'd like the wrapper to keep track and construct a scene that can be exported.
--
EDIT: Since recommendation is off-topic, I'll ask the following question.
What I need above seems like something obvious that many should have found useful. Since I can't find a library that accomplishes that, I'm wondering if my approach is unreasonable?
More specifically, how do people port their legacy opengl code; do they write the relevant part from scratch, or does everyone implement his own wrapper as I suggested?
What about constructing a scene to export to collada?
Posted also:
https://community.khronos.org/t/c-opengl-wrapper-interface-similar-to-fixed-pipeline-can-export-collada/105829
Although there are some parts in legacy OpenGL that are not optimized in current drivers (like glDrawPixels, the raster drawing operations and indexed color mode), between modern hardware and the modest requirements of legacy applications, legacy OpenGL stuff runs well enough on modern systems.
The main reason to "modernize" legacy OpenGL code is, if one want to make use of the modern features. Any sort of "wrapper" will just run into the same kind of design problems that the OpenGL API ran between OpenGL-1.5 to OpenGL-2.1: Lots of built-in variables, default state, implicit action, etc. etc. This is difficult to document properly, and even more difficult to make use of reliably. Which is the reason you usually don't find these kinds of wrappers.
If you find yourself in the situation, that you absolutely must port your legacy code to modern OpenGL, e.g. to be interoperable with core contexts, then your best course of action will be to do a proper rewrite. Replace implcit mode calls to filling vertex buffers, replace calls to glTexEnv…, glMaterial…, glLight… with loading appropriate shaders and setting their uniforms.
Or, if you want a quick and dirty method: Just create two contexts, a modern one, and a legacy one and switch between them; often you can establish "list" sharing between them.
Is there any proper way to access the low level OpenGL objects of VTK in order to modify them from a CUDA/OpenCL kernel using the openGL-CUDA/OpenCL interoperability feature?
Specifically, I would want to get the GLuint (or unsigned int) member from vtkOpenGLGPUVolumeRayCastMapper that points to the Opengl 3D Texture object where the dataset is stored, in order to bind it to a CUDA Surface to be able to access and modify its values from a CUDA kernel implemented by me.
For further information, the process that I need to follow is explained here:
http://rauwendaal.net/2011/12/02/writing-to-3d-opengl-textures-in-cuda-4-1-with-3d-surface-writes/
where the texID object used there (in Steps 1 and 2) is the equivalent to what I want to retrieve from VTK.
At a first look at the vtkOpenGLGPUVolumeRayCastMapper functions, I don't find an easy way to do this, rather than maybe creating a vtkGPUVolumeRayCastMapper subclass, but even in that case I am not sure what should I modify exactly, since I guess that some other members depend on the 3D Texture values, and should be also updated after modifying it.
So, do you know some way to do this?
Lots of thanks.
Subclassing might work, but you could probably avoid it if you wanted. The important thing is that you get the order of the GL/CUDA API calls in the right order.
First, you have to register the texture with CUDA. This is done using:
cudaGraphicsGLRegisterImage(&cuda_graphics_resource, texture_handle,
GL_TEXTURE_3D, cudaGraphicsRegisterFlagsSurfaceLoadStore);
with the stipulation that texture_handle is a GLuint written to by a call to glGenTextures(...)
Once you have registered the texture with CUDA, you can create the surface which can be read or written to in your kernel.
The only thing you have to worry about from here is that vtk does not use the texture in between a call to cudaGraphicsMapResources(...) and cudaGraphicsUnmapResources(...). Everything else should just be standard CUDA.
Also once you map the texture to CUDA and write to it within a kernel, there is no additional work besides unmapping the texture. GL will get the modified texture the next time it is used.
I'm working on an OpenGL project on Windows, using GLEW to provide the functionality the provided Windows headers lack. For shader support, I'm using NVIDIA's Cg. All the documentation and code samples I have read indicate that the following is the correct method for loading an using shaders, and I've implemented things this way in my code:
Create a Cg context with cgCreateContext.
Get the latest vertex and pixel shader profiles using cgGLGetLatestProfile with CG_GL_VERTEX and CG_GL_FRAGMENT, respectively. Use cgGLSetContextOptimalOptions to create the optimal setup for both profiles.
Using these profiles and shaders you have written, create shader programs using cgCreateProgramFromFile.
Load the shader programs using cgGLLoadProgram.
Then, each frame, for an object that uses a given shader:
Bind the desired shader(s) (vertex and/or pixel) using cgGLBindProgram.
Enable the profile(s) for the desired shader(s) using cgGLEnableProfile.
Retrieve and set any needed uniform shader parameters using cgGetNamedParameter and the various parameter setting functions.
Render your object normally
Clean up the shader by calling cgGLDisableProfile
However, things start getting strange. When using a single shader everything works just fine, but the act of loading a second shader with cgGLLoadProgram seems to make objects using the first one cease to render. Switching the draw order seems to resolve the issue, but that's hardly a fix. This problem occurs on both my and my partner's laptops (fairly recent machines with Intel integrated chipsets).
I tested the same code on my desktop with a GeForce GTX 260, and everything worked fine. I would just write this off as my laptop GPU not getting along with Cg, but I've successfully built and run programs that use several Cg shaders simultaneously on my laptop using the OGRE graphics engine (unfortunately the assignment I'm currently working on is for a computer graphics class, so I can't just use OGRE).
In conclusion, I'm stumped. What is OGRE doing that my code is not? Am I using Cg improperly?
You have to call cgGLEnableProfile before you call cgGLBindProgram. From your question it appears you do it the other way around.
From the Cg documentation for cgGLBindProgram:
cgGLBindProgram binds a program to the current state. The program must have been loaded with cgGLLoadProgram before it can be bound. Also, the profile of the program must be enabled for the binding to work. This may be done with the cgGLEnableProfile function.
In C, I can debug code like:
fprintf(stderr, "blah: %f", some_var);
in GLSL ... is there anyway for me to just dump out a value in a Vertex or Fragment shader? I don't care if it's slow; I just want to dump out the value. Ideally, I want a setup like the following:
normal state = run GLSL shader normally
press key 'd' = next frame is generated in ULTRA slow mode, where the "printfs" in the
Vertex/Fragment shader are executed and dumped out.
Is this feasible? (I don't care about performance; I just want to do this for one frame).
Thanks!
Unfortunately it's not possible directly. One possible solution though, that I end up using a lot (but I'm sure it's pretty common among GLSL developers) is to "print" values as colors, in place of your intended final result.
Of course this has many limitations; for one, you have to make sure that your value maps in a (0,1.0) range. Functions as mod, fract etc. turn out useful in these cases. But, in general, this is what I see as the "printf" equivalent in GLSL.
Instead of printing values, have you thought of trying a GLSL debugger?
For example, glslDevil will let you step through your shader's execution and examine the variables at each step.
Check out AMD CodeXL. It will let you step frame by frame to inspect opengl state values, shader code, and texture memory.
http://developer.amd.com/tools-and-sdks/heterogeneous-computing/codexl/
You can see the variable you want to check by copying its value in a uniform and then get that uniform with glGetUniformfv