What are The SPIR-V Capability (Geometry) Requirements - glsl

I have 2 framebuffers. First, one is layered. And renders HDR image to Cubemap.
In this Renderpass Geometry Shader is used.
Debug layer gives me the following error message.
[VAL][VUID-VkShaderModuleCreateInfo-pCode-01091] Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01091 ]
Object 0: handle = 0x14f9a58bfe8, type = VK_OBJECT_TYPE_DEVICE;
| MessageID = 0xa7bb8db6 | vkCreateShaderModule(): The SPIR-V Capability (Geometry) was declared, but none of the requirements were met to use it.
The Vulkan spec states: If pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.2.170.0/windows/1.2-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01091)
I searched for SPIR-V geometry shader requirements but I couldn't find what I am missing.
My Geometry shader code is
#version 450 core
layout(triangles, invocations = 6) in;
layout(triangle_strip, max_vertices = 3) out;
void main()
{
for(int i = 0; i < 3; i++)
{
gl_Layer = gl_InvocationID ;
gl_Position = gl_in[i].gl_Position + vec4(vec3(gl_InvocationID)/5 , 1);
EmitVertex();
}
EndPrimitive();
}

Related

Use matrix types as fragment shader output in OpenGL

In OpenGL, a matrix takes up multiple locations in a shader (one for each column). So when using a matrix in a vertex shader as an input it is necessary to call glVertexAttribPointer() multiple times.
I am wondering if it is possible to do something similar for matrix types as outputs in a fragment shader when rendering to multiple framebuffers. That is, I would have 4 different textures in a frame buffer bound to color attachments 0 through 3, and then I could have a layout(location = 0) out matrix4 out_mat that I could write to with the fragment shader.
Am I correct in assuming that this would work?
For the output of a fragment shader, a matrix data type is not allowed :
See OpenGL Shading Language 4.60 Specification - 4.3.6. Output Variables, page 54:
Fragment outputs output per-fragment data and are declared using the out storage qualifier. It is a compile-time error to use auxiliary storage qualifiers or interpolation qualifiers in a fragment shader output declaration. It is a compile-time error to declare a fragment shader output with, or that contains, any of the following types:
A boolean type
A double-precision scalar or vector (double, dvec2, dvec3, dvec4)
An opaque type
A matrix type
A structure
But the output of a fragment shader is allowed to be an array:
e.g.
layout (location = 0) out vec4 fragOut[4];
void main()
{
mat4 m = [...];
fragOut[0] = m[0];
fragOut[1] = m[1];
[...]
}
The matrix can be assigned to the array by an array constructor (see 4.1.13. Arrays, page 36):
layout (location = 0) out vec4 fragOut[4];
void main()
{
mat4 m = [...];
fragOut = vec4[4](m[0], m[1], m[2], m[3]);
}
GLSL spec says (Version 4.5, 4.3.6 Output Variables):
It is a compile-time error to declare a fragment shader output that contains any of the following:
...
Any matrix type
Therefore
layout(location = 0) out mat4 out_mat;
is illegal.
Instead you should output the elements of the matrix into four separate outputs:
layout(location = 0) out vec4 out_mat0;
layout(location = 1) out vec4 out_mat1;
layout(location = 2) out vec4 out_mat2;
layout(location = 3) out vec4 out_mat3;
void main() {
mat4 M = ...;
out_mat0 = M[0]; // column 0
out_mat1 = M[1]; // column 1
out_mat2 = M[2]; // column 2
out_mat3 = M[3]; // column 3
}

Layered rendering of a shadow cubemap

I'm trying to render a shadow cubemap in one pass, using layered rendering.
I've tried to be as thorough as possible :
I have bound a cubemap both depth attachment (GL_DEPTH_ATTACHMENT_32F) and color attachment 0 (GL_R32F) using glFramebufferTexture
I made sure to check whether, once the textures are attached to the FBO, that the framebuffer's completeness - it is complete
I have tried both geometry shader instancing using "layout(triangles, invocations=6) in;" and without (resorting to a for(int layer=0;layer<6;++layer) loop, setting gl_Layer = l, first for each primitive, then for each vertex)
Long story short, the first layer (ie. X+ in this case) gets rendered, but none of the others do, be it in the depth or color attachment.
It seems documentation on layered rendering is pretty sparse, even the red book spends at most half a page on it... Anyway :
The code :
Shaders :
Vertex :
#version 440 core
layout(location = 0) in vec3 attrPosition;
void main()
{
gl_Position = vec4(attrPosition, 1.0);
}
Geometry :
#version 440 core
layout(triangles, invocations = 6) in;
layout(triangle_strip, max_vertices = 18) out;
uniform mat4 dkModelMatrix;
uniform mat4 dkViewMatrices[6];
uniform mat4 dkProjectionMatrix;
void main()
{
gl_Layer = gl_InvocationID;
for(int i = 0; i < 3; ++i)
{
gl_Layer = gl_InvocationID;
gl_Position = dkProjectionMatrix * dkViewMatrices[gl_InvocationID] * dkModelMatrix * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
Fragment :
#version 440 core
layout(location = 0) out vec4 dkFragCoord;
void main()
{
dkFragCoord = vec4( vec3(float(gl_Layer) * 0.1 + 0.5) , 1.0);
}
C++ (mostly using my engine's classes, which actually do the bare minimum and has already been tested, in the case of FBOs, with 2D (spot) shadowmaps) :
Shadowmap-related variables creation : https://gist.github.com/xtrium-lnx/77d8989b3c2370607cfc
Shadowmap rendering : https://gist.github.com/xtrium-lnx/387b97c077525be60bb4

JOGL, opengl 4.3, passing color vector from geometry shader, to fragment shader

I am using a book called Opengl SuperBible 6th edition. I am using JOGL 2.5.1 API. Everytihing was working fine, until I created geometry shader (exercise on page 37). When I try to pass color vector from geometry shader to fragment shader, the Java virtual machine crashes. I have also implemented GLSL error check at shader creation and it shows nothing. I really want to know what is the catch here. here is my code from vertex shader to fragment shader. Funny thing is the program crashes only when i send color from geometry shader to fragment shader. If i set color manualy in fragment shader the program works.
VERTEX SHADER:
#version 430 core
layout (location = 0) in vec4 offset;
layout (location = 1) in vec4 color;
out vec4 vs_color;
void main(void){
const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4( 0.25, 0.25, 0.5, 1.0));
gl_Position = vertices[gl_VertexID] + offset;
vs_color = color;
}
TESSELATION CONTROL SHADER:
#version 430 core
layout (vertices = 3) out;
in vec4 vs_color[];
out vec4 tsc_color[];
void main(void){
if (gl_InvocationID == 0){
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
tsc_color[0] = vs_color[0];
}
TESSELATION EVALUATION SHADER:
#version 430 core
layout (triangles, equal_spacing, cw) in;
in vec4 tsc_color[];
out vec4 tse_color[];
void main(void){
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position +
gl_TessCoord.y * gl_in[1].gl_Position +
gl_TessCoord.z * gl_in[2].gl_Position);
tse_color[0] = tsc_color[0];
}
GEOMETRY SHADER:
#version 430 core
layout (triangles) in;
layout (points, max_vertices = 3) out;
in vec4 tse_color[];
out vec4 geo_color;
void main(void){
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
geo_color = tse_color[0];
}
FRAGMENT SHADER:
#version 430 core
in vec4 geo_color;
out vec4 color;
void main(void){
//color = vec4(0.0f, 0.8f, 1.0f, 1.0f); for manual setting
color = geo_color;
}
THE ERROR THAT OCCURES:
glLinkProgram(<int> 0x6)GLDebugEvent[ id 0x7d1
type Error
severity High: dangerous undefined behavior
source GLSL or extension compiler
msg glLinkProgram failed to link a GLSL program with the following program info log: 'Vertex shader(s) failed to link, tessellation control shader(s) failed to link, tessellation evaluation shader(s) failed to link, geometry shader(s) failed to link, fragment shader(s) failed to link.
Vertex link error: INVALID_OPERATION.
ERROR: error(#275) Symbol "tse_color" is defined with 2 different types between two stages
tessellation control link error: INVALID_OPERATION.
ERROR: error(#275) Symbol "tse_color" is defined with 2 different types between two stages
tessellation evaluation link error: INVALID_OPERATION.
ERROR: error(#275) Symbol "tse_color" is defined with 2 different types between two stages
geometry link error: INVALID_OPERATION.
ERROR: error(#275) Symbol "tse_color" is defined with 2 different types between two stages
fragment link error: INVALID_OPERATION.
ERROR: error(#275) Symbol "tse_color" is defined with 2 different types between two stages
'
when 1401907851402
source 4.4 (Core profile, arb, debug, ES2 compat, ES3 compat, FBO, hardware) - 4.4.12874 Core Profile/Debug Context 14.100.0.0 - hash 0x14e08f00]
Tessellation Evaluation Shaders only output 1 vertex. I do not know why you have declared out vec4 tse_color[];, but that is a mistake.
// out vec4 tse_color[]; // WRONG
out vec4 tse_color; // * Fixed
[...]
// tse_color[0] = tsc_color[0]; // WRONG
tse_color = tsc_color[0]; // * Fixed
Finally, you are only outputting color to a single vertex for every invocation of your control shader, when you should be outputting multiple. To pass your per-vertex color through the control shader, you need the following:
tsc_color [gl_InvocationID] = vs_color [gl_InvocationID];
Now, here is where things get strange... you are only referencing the first color in your patch for each evaluated vertex. I think what you actually want is an input/output variable qualified with patch storage. That will allow you to create exactly 1 instance of the variable shared across all invocations, sort of like a provoking vertex only for tessellation.

GLSL 1.5 - rendering to different layers of texture array

I have GL_TEXTURE_2D_ARRAY and I do this:
1. Render everything I want to FBO to texture array
2. Sample that array in the "main stage" of rendering
To achieve the first goal I've added a little geometry shader with gl_Layer calls to each primitive. Also, I've implemented some, let me say, "translation" thing similar to this Nvidia tutorial in my shaders that I use for the second stage of rendering.
So, what's my problem :
Condition: same vertices, same FBO, same shaders, same texture array
1) Rebinding rendering target multiply times in my FBO with glFramebufferTextureLayer calls works fine.
2) Saving texture array as glFramebufferTexture and only changing gl_Layer value leads to unexpected behaviour (first layer (0 in the code) is correct, every layer I try render next is invalid).
3) I don't want to 1) , I want to do 2) . How do I do that?
My shaders I use when rendering the FBO.
//vertex shader
#version 150 core
uniform mat4 orthoView;
in vec4 in_Position;
void main(void) {
gl_Position = orthoView * in_Position;
}
//geometry
#version 150 core
uniform int lr;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
out int gl_Layer;
void main(void){
//pass-thru!
for(int i=0; i<3; i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
gl_Layer = lr;
EndPrimitive();
}
//fragment is empty
EDIT:
Thanks to everyone for help! My problem is solved now, here is my geometry shader:
#version 150 core
uniform int lr;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main(void){
//pass-thru!
for(int i=0; i<3; i++)
{
gl_Layer = lr;
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
gl_Layer, like all geometry shader outputs is a per-vertex output. Which vertex controls the layer for a particular primitive is implementation-defined. In your case, there's no reason not to set it in your loop, before the EmitVertex call.
I haven't actually used gl_Layer before, but looking at the documentation, it sounds like it is a per-vertex attribute (which is odd...).
The actual layer used will come from one of the vertices in the primitive being shaded
So try to set the value inside the for loop, before the EmitVertex, maybe?

texture3d generates GL_INVALID_OPERATION

Have a strange issue with my glsl shader. It renders nothing (eg black screen) and makes my glDrawElements cast a GL_INVALID_OPERATION. The shader in use is shown bellow. When I comment out the line with v = texture3D(texVol,pos).r; and replace it with v = 0.4; it outputs what is expected (orange-like color) and no gl errors is generated.
uniform sampler2D texBack;
uniform sampler3D texVol;
uniform vec3 texSize;
uniform vec2 winSize;
uniform float iso;
varying vec3 inCoords;
vec4 raytrace(in vec3 entryPoint,in vec3 exitPoint){
vec3 dir = exitPoint - entryPoint;
vec3 pos = entryPoint;
vec4 color = vec4(0.0,0.0,0.0,0.0);
int steps = int(2.0*length(texSize));
dir = dir * (1.0/steps);
vec3 n;
float v,m=0.0,avg=0.0,avg2=0.0;
for(int i = 0;i<steps || i < 2500;i++){
v = texture3D(texVol,pos).r;
m = max(v,m);
avg += v;
pos += dir;
}
return vec4(avg/steps,m,0,1);
}
void main()
{
vec2 texCoord = gl_FragCoord.xy/winSize;
vec3 exitPoint = texture2D(texBack,texCoord).xyz;
gl_FragColor = raytrace(inCoords,exitPoint);
}
I am using an VBO for rendering a color cube as entry and exist point for my rays. They are stored in FBOs and they look ok when I render them directly to the screen.
I have tried chaning to glBegin/glEnd and draw the cube with quads and then I get the same errors.
I cant find what I am doing wrong and now I need your help. Why is my texture3D generating GL_INVALID_OPERATION?
Note:
I have enabled both 2d and 3d textures.
Edit:
I've just uploaded the whole project to github. browse to for more code https://github.com/r-englund/rGraphicsLibrary
This is tested on both Intel HD 3000 and Nvidia GT550m
According to OpenGL specification glDrawElements() generates GL_INVALID_OPERATION in the following cases:
If a geometry shader is active and mode is incompatible with the input primitive type of the geometry shader in the currently installed program object.
If a non-zero buffer object name is bound to an enabled array or the element array and the buffer object's data store is currently mapped.
This means the problem has nothing to do with your fragment shader. If you don't use geometry shaders, you should fix the buffer objects accordingly.
It looks like your are not providing additional relevant information in your question.