Fragment shader for unsigned integer textures - opengl

I am using following shader for unsigned integer textures to read a data:
Fragment shader:
Code :
#version 150
out uvec4 fragColor;
uniform uint factor;
void main()
{
uint temp=factor;
temp=temp/2;
fragColor = uvec4(temp,temp,temp,temp);
}
But i am getting error on driver A:
"Compile failed.
ERROR: 0:7: '/' : Wrong operand types. No operation '/' exists that takes a left-hand operand of type 'uint' and a right operand of type 'const int' (and there is no acceptable conversion)
ERROR: 1 compilation errors. No code generated."
on driver B it runs perfectly. Is driver A is buggy or my shader is wrong? if wrong, how can i achieve the same result?

Try this:
temp = temp / uint(2);

GLSL does not allow implicit conversions between signed and unsigned ints, so both operands of a binary operand must be the same. Use:
temp = temp / 2u;
to use an unsigned int constant.

Related

GLSL - why can't index array with a `uint64_t`?

I have this GLSL code that compiles fine:
#version 450
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
layout (local_size_x = 256) in;
layout(binding = 1) buffer OutBuffer {
uint64_t outBuf[];
};
void main()
{
uint myId = gl_GlobalInvocationID.x;
outBuf[myId] = 0;
}
If I change the type of myId from uint to uint64_t it doesn't compile:
ERROR: calc.comp.glsl:13: '[]' : scalar integer expression required
I can just use uint, but I'm curious why you can't use uint64_t.
Anything other than uint or int needs to be explicitly casted to one of these types when used for indexing arrays:
uint64_t myId = gl_GlobalInvocationID.x;
outBuf[uint(myId)] = 0;
The spec GL_EXT_shader_explicit_arithmetic_types_*** doesn't seem to say anything about using the types it introduces to index arrays.
It defines implicit promotion rules such as uint16_t -> uint32_t (defined to be equivalent to uint).
and these of course work for function parameters,
but curiously you can't even use uint16_t as an array index and expect it to be implicitly promoted to 'uint32_t'; you need to explicitly cast it to uint (or uint32_t).
So we're at the mercy of the original GLSL spec when indexing arrays; use uint or sint, which are the only scalar integer types it knows.

How to convert uint64_t to sampler2D?

I want to use bindless textures, but spirv does not support it. I found here: https://www.khronos.org/opengl/wiki/Bindless_Texture that uint64_t can be converted to a sampler2D.
uint64_t values can be converted to any sampler or image type using constructors: sampler2DArray(some_uint64). They can also be converted back to 64-bit integers.
and I thought that I could upload a bindless handle as the uint64_t and then convert it to the sampler2D.
spir-v compiler gives me them errors:
error: 'sampler/image' : cannot construct this type
error: 'sampler2D' : sampler-constructor requires two arguments
error: 'constructor' : too many arguments
error: 'assign' : cannot convert from ' const float' to 'layout( location=0) out highp 4-component vector of float'
shader code
#version 460 core
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_EXT_scalar_block_layout : require
layout(location = 0) out vec4 f_color;
layout(location = 0) in vec2 v_uv;
layout(std430, binding = 5) uniform Textures
{
uint64_t albedo;
};
void main()
{
f_color = texture(sampler2D(albedo), v_uv);
}
is it possible to convert uint64_t to sampler2D? How to do it?
As with all GLSL extensions, you must explicitly enable them. However, you have a more interesting problem: bindless texturing cannot be used with SPIR-V. What you want to do is only possible if you feed the GLSL directly to OpenGL, without the SPIR-V intermediary.
Vulkan does not support bindless textures; you need to use arrays of samplers to get an equivalent effect. And OpenGL doesn't support GL_EXT_scalar_block_layout. So the code you're writing cannot be used by any graphics system.

error: cast from 'char*' to 'unsigned int' loses precision

I am compiling a code, which gives me error in the following function :
inline char *align(char *var, DataType_e type)
{
return (DataTypeSize[type] == 0) ? var :
(char*) (((unsigned int)(var) + DataTypeSize[type]-1) /
DataTypeSize[type] * DataTypeSize[type]);
}
The following error comes in line with "(unsigned int)(var)" :
error: cast from 'char*' to 'unsigned int' loses precision
If i change "unsigned int" to "unsigned long", the compilation works but i don't get the expected results while running my program. Any idea on how to resolve this issue ?
In C you should use [u]intptr_t if you need to convert a pointer to an integer type (but which you should avoid in the first place).
If they exist, these types are guaranteed to not lose information.
The uintptr_t type is the same size as a pointer to POD. Pointers to other data types, and pointers to member functions in particular, can be larger.
inline char *align(char *var, DataType_e type)
{
size_t alignSize = DataTypeSize[type];
if (1 >= alignSize) {
return var;
}
uintptr_t varInt = reinterpret_cast<uintptr_t>(var);
varInt = alignSize * ((varInt + alignSize - 1) / alignSize);
return reinterpret_cast<char *>(varInt);
}
When you're going to do math operations with pointers you should use pointer arithmetics instead of casting your pointer values to 'int' or 'long', calculate and cast back to pointer. This is prone for bad results, because the compiler can't respect alignment rules for the calculations.
I'm pretty sure that the 'unexpected' result of the function in your example has nothing to do with the cast at all. You should explain more about the calculations done with the DataSize[type] values and what you want to achieve with it.

GLSL texelFetchOffset works with isampler2D but not usampler2D?

In a fragment shader, the following compiles fine:
uniform isampler2D testTexture;
/* in main() x, y, xoff and yoff are declared as int and assigned here, then... */
int tmp = texelFetchOffset(testTexture, ivec2(x, y), 0, ivec2(xoff, yoff)).r;
However, the following does not compile:
uniform usampler2D testTexture;
/* in main() x, y, xoff and yoff are declared as uint and assigned here, then... */
uint tmp = texelFetchOffset(testTexture, uvec2(x, y), 0, uvec2(xoff, yoff)).r;
The OpenGL 4.2 driver gives the following compiler error message:
error C1115: unable to find compatible overloaded function "texelFetchOffset(usampler2D, uvec2, int, uvec2)
This is Nvidia's Linux driver 290.* for a Quadro 5010M -- but I'm wondering if I made a (beginner) mistake and was not working to spec somehow here?
The texelFetchOffset function that takes a usampler2D still takes an ivec2 as its texture coordinates and offset. The u only applies to the sampler type and return value; not everything about the function becomes unsigned.
And remember: OpenGL doesn't allow implicit conversions between unsigned and signed integer types.

GLSL <> operators on a vec4

I'm looking at some newer GLSL code that doesn't compile to my current version of OpenGL and I'm wondering what the short form of the following means:
vec4 base;
if (base < 0.5) {
result = (2.0 * base * blend);
}
Is this equivalent to:
if (base.r < 0.5 && base.g < 0.5 && base.b < 0.5 && base.a < 0.5) {
result.r = 2.0 * base.r * blend.r;
result.g = 2.0 * base.g * blend.g;
result.b = 2.0 * base.b * blend.b;
result.a = 2.0 * base.a * blend.a;
}
Edit:
Error:
Fragment shader failed to compile with the following errors:
Wrong operand types no operation '<' exists that takes a left-hand operand of type 'highp 3-component vector of float' and a right operand of type 'const float' (or there is no acceptable conversion)
I've also tried:
(base.rgb < vec3(0.5))
... Wrong operand types no operation '<' exists that takes a left-hand operand of type 'highp 3-component vector of float' and a right operand of type 'const highp 3-component vector of float'
I'm assuming this is because I'm using GLSL 1.2.
ATI Radeon 3450
From the spec, section 5.9 (top of page 38):
The relational operators greater than
(>), less than (<), greater than or
equal (>=), and less than or equal
(<=) operate only on scalar integer
and scalar floating-point expressions.
The result is scalar Boolean. Either
the operands’ types must match, or the
conversions from Section 4.1.10
“Implicit Conversions” will be applied
to the integer operand, after which
the types must match. To do
component-wise relational comparisons
on vectors, use the built-in functions
lessThan, lessThanEqual, greaterThan,
and greaterThanEqual.
Looks like you want the lessThan function. Check section 8.6 (page 62).
lessThan() - http://www.opengl.org/ (see also: all())