First of all, you need a handle (some kind of pointer again, but don't think of it as a pointer, yucks) for a given texture.
long handle = ARBBindlessTexture.glGetTextureHandleARB(textureID);
Afterwards, the handle has to be made resident. I think that's something you need for the combination with partially resident textures.
ARBBindlessTexture.glMakeTextureHandleResidentARB(handle);
This was the easy part. Now, you have to use the handle in our shaders somehow. The easiest way would be to use it as a uniform.
ARBBindlessTexture.glUniformHandleui64ARB(location, handle);
Inside your shader, you have to use the handle. But what datatype should one use? Maybe I missed something elementary, but there's only one proper way, namely use a datatype made available through an nvidia extension. Since bindless textures are available through an extension as well, here are both calls that you (probably) need:
#extension GL_NV_gpu_shader5 : enable
#extension GL_ARB_bindless_texture : enable
And now, you can use tha datatype uint64_t. So your uniform would be a uint64_t.
That would work. But most probable, you want to have your data in a uniform or storage buffer, probably together with some other data and datatypes. So here's what I did.
Use a DoubleBuffer (Java native buffer, available via BufferUtils.createDoubleBuffer(int size)) for your data. Since doubles are twice the size of a float, which is 4 byte, we have 8 bytes per texture handle, which is 64 bits, which is the same as a uint64's size, so that's enough. Now one has to take the generated handle's bits and put them into the buffer (for example a ssbo) as they are. This can be done like so:
GL15.glBufferSubData(GL43.GL_SHADER_STORAGE_BUFFER, offset * primitiveByteSize, values);
-
Where primitiveByteSize is 8 in this case. Since we use the underlying buffer as a DoubleBuffer, we have to provide a double value for the handle (or use it as a byte buffer, but nevertheless we need the correct bits or bytes). You can convert a Java long to and from a double like this:
Double.longBitsToDouble(longValue)
Double.doubleToLongBits(doubleValue)
Afterwars, the shader can take the value as a said uint64_t and cast it to a sampler. Sounds ugly, maybe it is.
color = texture(sampler2D(uint64_t(material.handleDiffuse)), UV);
That is the whole story, took me a while to figure it out.
Keine Kommentare:
Kommentar veröffentlichen