]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/spirv.cpp
Implement tessellation shaders in the shader compiler
[libs/gl.git] / source / glsl / spirv.cpp
index 9cb1b7f2e112a8d8d06d85dc92ab3f1d8561dcd5..b2eac3f0fe1925b11cc586e3e3485d19735ca388 100644 (file)
@@ -187,6 +187,14 @@ SpirVGenerator::BuiltinSemantic SpirVGenerator::get_builtin_semantic(const strin
                return BUILTIN_INVOCATION_ID;
        else if(name=="gl_Layer")
                return BUILTIN_LAYER;
+       else if(name=="gl_TessLevelOuter")
+               return BUILTIN_TESS_LEVEL_OUTER;
+       else if(name=="gl_TessLevelInner")
+               return BUILTIN_TESS_LEVEL_INNER;
+       else if(name=="gl_TessCoord")
+               return BUILTIN_TESS_COORD;
+       else if(name=="gl_PatchVerticesIn")
+               return BUILTIN_PATCH_VERTICES;
        else if(name=="gl_FragCoord")
                return BUILTIN_FRAG_COORD;
        else if(name=="gl_PointCoord")
@@ -199,6 +207,18 @@ SpirVGenerator::BuiltinSemantic SpirVGenerator::get_builtin_semantic(const strin
                return BUILTIN_SAMPLE_POSITION;
        else if(name=="gl_FragDepth")
                return BUILTIN_FRAG_DEPTH;
+       else if(name=="gl_NumWorkGroups")
+               return BUILTIN_NUM_WORKGROUPS;
+       else if(name=="gl_WorkGroupSize")
+               return BUILTIN_WORKGROUP_SIZE;
+       else if(name=="gl_WorkGroupID")
+               return BUILTIN_WORKGROUP_ID;
+       else if(name=="gl_LocalInvocationID")
+               return BUILTIN_LOCAL_INVOCATION_ID;
+       else if(name=="gl_GlobalInvocationID")
+               return BUILTIN_GLOBAL_INVOCATION_ID;
+       else if(name=="gl_LocalInvocationIndex")
+               return BUILTIN_LOCAL_INVOCATION_INDEX;
        else
                throw invalid_argument("SpirVGenerator::get_builtin_semantic");
 }
@@ -1759,6 +1779,12 @@ void SpirVGenerator::visit(VariableDeclaration &var)
                        BuiltinSemantic semantic = get_builtin_semantic(var.name);
                        writer.write_op_decorate(var_id, DECO_BUILTIN, semantic);
                }
+               if(var.sampling=="flat")
+                       writer.write_op_decorate(var_id, DECO_FLAT);
+               if(var.sampling=="centroid")
+                       writer.write_op_decorate(var_id, DECO_CENTROID);
+               if(var.sampling=="patch")
+                       writer.write_op_decorate(var_id, DECO_PATCH);
 
                if(init_id && current_function)
                {
@@ -1777,8 +1803,11 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
        switch(stage->type)
        {
        case Stage::VERTEX: writer.write(0); break;
+       case Stage::TESS_CONTROL: writer.write(1); break;
+       case Stage::TESS_EVAL: writer.write(2); break;
        case Stage::GEOMETRY: writer.write(3); break;
        case Stage::FRAGMENT: writer.write(4); break;
+       case Stage::COMPUTE: writer.write(5); break;
        default: throw internal_error("unknown stage");
        }
        writer.write(func_id);
@@ -1802,6 +1831,12 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
                use_capability(CAP_GEOMETRY);
                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INVOCATIONS, 1);
        }
+       else if(stage->type==Stage::TESS_CONTROL || stage->type==Stage::TESS_EVAL)
+       {
+               use_capability(CAP_TESSELLATION);
+       }
+
+       unsigned local_size[3] = { 0, 1, 1 };
 
        for(const InterfaceLayout *i: interface_layouts)
        {
@@ -1818,14 +1853,44 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
                                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_TRIANGLES);
                        else if(q.name=="triangles_adjacency")
                                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_TRIANGLES_ADJACENCY);
+                       else if(q.name=="quads")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_QUADS);
+                       else if(q.name=="isolines")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_ISOLINES);
                        else if(q.name=="line_strip")
                                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_LINE_STRIP);
                        else if(q.name=="triangle_strip")
                                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_TRIANGLE_STRIP);
-                       else if(q.name=="max_vertices")
+                       else if(q.name=="max_vertices" || q.name=="vertices")
                                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, q.value);
+                       else if(q.name=="cw")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_VERTEX_ORDER_CW);
+                       else if(q.name=="ccw")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_VERTEX_ORDER_CCW);
+                       else if(q.name=="equal_spacing")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_EQUAL);
+                       else if(q.name=="fractional_even_spacing")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_FRACTIONAL_EVEN);
+                       else if(q.name=="fractional_odd_spacing")
+                               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_FRACTIONAL_ODD);
+                       else if(q.name=="local_size_x")
+                               local_size[0] = q.value;
+                       else if(q.name=="local_size_y")
+                               local_size[1] = q.value;
+                       else if(q.name=="local_size_z")
+                               local_size[2] = q.value;
                }
        }
+
+       if(stage->type==Stage::COMPUTE && local_size[0])
+       {
+               writer.begin_op(content.exec_modes, OP_EXECUTION_MODE);
+               writer.write(func_id);
+               writer.write(EXEC_LOCAL_SIZE);
+               for(unsigned j=0; j<3; ++j)
+                       writer.write(local_size[j]);
+               writer.end_op(OP_EXECUTION_MODE);
+       }
 }
 
 void SpirVGenerator::visit(FunctionDeclaration &func)