OpenGL equivalent of D3DCAPS9 - opengl

I need to know what is the maximum vertex index that the user's hardware can handle by using OpenGL.
With Direct3D I use the D3DCAPS9 struct to do this.
Is there an equivalent of D3DCAPS9 on OpenGL to get this information?
Or is there an other method to get the maximum size of a mesh using OpenGL?

There is no restriction to the size of mesh besides the GPU memory size. Due to this, there is no way to query such a limit.
Note, that the datatype used for the element array buffer (index buffer) might add some constraints. When, for example, using GL_UNSIGNED_SHORT, you can draw a maximum of 2^16 different vertices. GL_UNSIGNED_INT allows 2^32 different values which should be enough for most meshes.

Related

Is there a workaround for increasing GL_MAX_ARRAY_TEXTURE_LAYERS?

I'm using a texture array to render Minecraft-style voxel terrain. It's working fantastic, but I noticed recently that GL_MAX_ARRAY_TEXTURE_LAYERS is alot smaller than GL_MAX_TEXTURE_SIZE.
My textures are very small, 8x8, but I need to be able to support rendering from an array of hundreds to thousands of them; I just need GL_MAX_ARRAY_TEXTURE_LAYERS to be larger.
OpenGL 4.5 requires GL_MAX_ARRAY_TEXTURE_LAYERS be at least 2048, which might suffice, but my application is targeting OpenGL 3.3, which only guarantees 256+.
I'm drawing up blanks trying to figure out a prudent workaround for this limitation; dividing up the rendering of terrain based on the max number of supported texture layers does not sound trivial at all to me.
I looked into whether ARB_sparse_texture could help, but GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB is the same as GL_MAX_ARRAY_TEXTURE_LAYERS; that extension is just a workaround for VRAM usage rather than layer usage.
Can I just have my GLSL shader access from an array of sampler2DArray? GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS has to be at least 80+, so 80+ * 256+ = 20480+ and that would enough layers for my purposes. So, in theory could I do something like this?
const int MAXLAYERS = 256;
vec3 texCoord;
uniform sampler2DArray[] tex;
void main()
{
int arrayIdx = int(texCoord.z + 0.5f) / MAXLAYERS 256
float arrayOffset = texCoord.z % MAXLAYERS;
FragColor = texture(tex[arrayIdx],
vec3(texCoord.x, texCoord.y, arrayOffset));
}
It would be better to ditch array textures and just use a texture atlas (or use an array texture with each layer containing lots of sub-textures, but as I will show, that's highly unnecessary). If you're using textures of such low resolution, you probably aren't using linear interpolation, so you can easily avoid bleed-over from neighboring texels. And even if you have trouble with bleed-over, it can easily be fixed by adding some space between the sub-textures.
Even if your sub-textures need to be 10x10 to avoid bleed-over, a 1024x1024 texture (the minimum size GL 3.3 requires) gives you 102x102 sub-textures, which is 10'404 textures. Which ought to be plenty. And if its not, then make it an array texture with however many layers you need.
Arrays of samplers will not work for your purpose. First, you cannot declare an unsized uniform array of any kind. Well you can, but you have to redeclare it with a size at some point in your shader, so there's no much point to the unsized declaration. The only unsized arrays you can have are in SSBOs, as the last element of the SSBO.
Second, even with a size, the index you use for arrays of opaque types must be a dynamically uniform. And since you're trying to draw all of the faces of the cubes in one draw calls, and each face can have select from a different layer, there is no intent for this expression's value to be dynamically uniform.
Third, even if you did this with bindless texturing, you would run into the same problem: unless you're on NVIDIA hardware, the sampler you pick must be a dynamically uniform sampler. Which requires the index into the array of samplers to be dynamically uniform. Which yours is not.

understanding how textures work with CUDA

I got confused of how textures work with CUDA
as when I do device Query "on my GTX 780" I find this:
Maximum Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096)
now when I investigated CUDA "particles example", I found this:
checkCudaErrors(cudaBindTexture(0, oldPosTex, sortedPos, numParticles*sizeof(float4)));
where numParticles in my case I have raised it to 1024 * 1024 * 2 (around 2.1 millions)
how does this fit in the 1D texture??
also inside the kernels I've found this "need more explain please as everything here is connected"
texture<float4, 1, cudaReadModeElementType> oldPosTex;
#define FETCH(t, i) tex1Dfetch(t##Tex, i)
at kernel:
float4 pos = FETCH(oldPos, sortedIndex);
now what I need to know also, I can use this texture "with its defined size numParticles*sizeof(float4) in a frame buffer draw instead of drawing a VBO?
how does this fit in the 1D texture?
The texture hardware consists of two main parts, the texture filtering hardware and the texture cache. Texture filtering includes functionality such as interpolation, addressing by normalized floating point coordinates and handling out-of-bounds addresses (clamp, wrap, mirror and border addressing modes). The texture cache can store data in a space filling curve to maximize 2D spatial locality (and thereby the cache hit rate). It can also store data in a regular flat array.
The Maximum Texture Dimension Size refers to limitations in the texture filtering hardware, not the texture caching hardware. And so, it refers to limits you may hit when using functions like tex2D() but not when using functions like tex1Dfetch(), which performs an unfiltered texture lookup. So, code you gave is probably setting things up for tex1Dfetch().
need more explain please as everything here is connected
This question is too broad and may be why your question was downvoted.
now what I need to know also, I can use this texture "with its defined size numParticles*sizeof(float4) in a frame buffer draw instead of drawing a VBO?
This is not a CUDA question as CUDA cannot draw anything. You should look into CUDA OpenGL interop to see if your question is answered there. If it's not, you should create a new question and describe your question more clearly.

Transferring large voxel data to a GLSL shader

I'm working a program which renders a dynamic high resolution voxel landscape.
Currently I am storing the voxel data in 32x32x32 blocks with 4 bits each:
struct MapData {
char data[32][32][16];
}
MapData *world = new MapData[(width >> 5) * (height >> 5) * (depth >> 5)];
What I'm trying to do with this, is send it to my vertex and fragment shaders for processing and rendering. There are several different methods I've seen to do this, but I have no idea which one will be best for this.
I started with a sampler1D format, but that results in floating point output between 0 and 1. I also had the hinting suspicion that it was storing it as 16 bits per voxel.
As for Uniform Buffer Objects I tried and failed to implement this.
My biggest concern with all of this is not having to send the whole map to the GPU every frame. I want to be able to load maps up to ~256MB (1024x2048x256 voxels) in size, so I need to be able to send it all once, and then resend only the blocks that were changed.
What is the best solution for this short of writing OpenCL to handle the video memory for me. If there's a better way to store my voxels that makes this easier, I'm open to other formats.
If you just want a large block of memory to access from in a shader, you can use a buffer texture. This obviously requires a semi-recent GL version (3.0 or better), so you need DX10 hardware or better.
The concept is pretty straightforward. You make a buffer object that stores your data. You create a buffer texture using the typical glGenTextures command, then glBindTexture it to the GL_TEXTURE_BUFFER target. Then you use glTexBuffer to associate your buffer object with the texture.
Now, you seem to want to use 4 bits per voxel. So your image format needs to be a single-channel, unsigned 8-bit integral format. Your glTexBuffer call should be something like this:
glTexBuffer(GL_TEXTURE_BUFFER, GL_RUI8, buffer);
where buffer is the buffer object that stores your voxel data.
Once this is done, you can change the contents of this buffer object using the usual mechanisms.
You bind the buffer texture for rendering just like any other texture.
You use a usamplerBuffer sampler type in your shader, because it's an unsigned integral buffer texture. You must use the texelFetch command to access data from it, which takes integer texture coordinates and ignores filtering. Which is of course exactly what you want.
Note that buffer textures do have size limits. However, the size limits are often some large percentage of video memory.

Check GPU OpenGL Limits

I was wondering if there is an easy way to query (programatically) the GPU OpenGL Limits for the following features:
- maximum 2D texture size
- maximum 3D texture size
- maximum number of vertex shader attributes
- maximum number of varying floats
- number of texture image units (in vertex shader, and in fragment shader)
- maximum number of draw buffers
I need to know these numbers in advance before writing my GPU Research Project.
glGet() is your friend, with:
GL_MAX_3D_TEXTURE_SIZE
GL_MAX_TEXTURE_SIZE
GL_MAX_VERTEX_ATTRIBS
GL_MAX_VARYING_FLOATS
GL_MAX_TEXTURE_UNITS
GL_MAX_DRAW_BUFFERS
e.g.:
GLint result;
glGetIntegerv(GL_MAX_VARYING_FLOATS, &result);
Not quite sure what your project is setting out to achieve, but you might be interested in OpenCL if it's general purpose computing and you weren't already aware of it. In particular Cl/GL interop if there is a graphics element too and your hardware supports it.
As Damon pointed out in the comments in practice it may be more complex than this for texture sizes. The problems arise because rendering may fallback from hardware to software for some sizes of textures, and also because the size of a texture varies depending upon the pixel format used. To work around this it is possible to use GL_PROXY_TEXTURE_* with glTexImage*.
As a complement to what was said by "awoodland" and if you still do not know ... i think you should take a look at GLEW...
GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the target platform.
http://glew.sourceforge.net/

OpenGL: Buffer object performance issue

I have a question related to Buffer object performance. I have rendered a mesh using standard Vertex Arrays (not interleaved) and I wanted to change it to Buffer Object to get some performance boost. When I introduce buffers object I was in shock when I find out that using Buffers object lowers performance four times. I think that buffers should increase performance. Does it true? So, I think that I am doing something wrong...
I have render 3d tiled map and to reduce amount of needed memory I use only a single tile (vertices set) to render whole map. I change only texture coordinates and y value in vertex position for each tile of map. Buffers for position and texture coords are created with GL_DYNAMIC_DRAW parameter. The buffer for indices is created with GL_STATIC_DRAW because it doesn't change during map rendering. So, for each tile of map buffers are mapped and unmapped at least one time. Should I use only one buffer for texture coords and positions?
Thanks,
Try moving your vertex/texture coordinates with GL_MODELVIEW/GL_TEXTURE matrices, and leave buffer data alone (GL_STATIC_DRAW alone). e.g. if tile is of size 1x1, create rect (0, 0)-(1, 1) and set it's position in the world with glTranslate. Same with texture coordinates.
VBOs are not there to increase performance of drawing few quads. Their true power is seen when drawing meshes with thousands of polygons using shaders. If you don't need any forward compatibility with newer opengl versions, I see little use in using them to draw dynamically changing data.
If you need to update the buffer(s) each frame you should use GL_STREAM_DRAW (which hints that the buffer contents will likely be used only once) rather than GL_DYNAMIC_DRAW (which hints that they will be but used a couple of times before being updated).
As far as my experience goes, buffers created with GL_STREAM_DRAW will be treated similarly to plain ol' arrays, so you should expect about the same performance as for arrays when using it.
Also make sure that you call glMapBuffer with the access parameter set to GL_WRITE_ONLY, assuming you don't need to read the contents of the buffer. Otherwise, if the buffer is in video memory, it will have to be transferred from video memory to main memory and then back again (well, that's up to the driver really...) for each map call. Transferring to much data over the bus is a very real bottleneck that's quite easy to bump into.