]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/spirv.cpp
Preparatory refactoring of the texelFetch implementation
[libs/gl.git] / source / glsl / spirv.cpp
index e1ba981b552f1b63de515334bdd516ed0846159f..61e5937856b30d7abc38afc2d5143b03e1ca4b1e 100644 (file)
@@ -111,6 +111,7 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] =
        { "textureSize", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query },
        { "textureQueryLod", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query },
        { "textureQueryLevels", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query },
+       { "textureSamples", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query },
        { "texture", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture },
        { "textureLod", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture },
        { "texelFetch", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texel_fetch },
@@ -1021,18 +1022,22 @@ void SpirVGenerator::visit(TernaryExpression &ternary)
        writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0);  // Selection control (none)
        writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, condition_id, true_label_id, false_label_id);
 
+       std::map<const VariableDeclaration *, Id> saved_load_ids = variable_load_ids;
+
        writer.write_op_label(true_label_id);
        ternary.true_expr->visit(*this);
        Id true_result_id = r_expression_result_id;
        true_label_id = writer.get_current_block();
        writer.write_op(content.function_body, OP_BRANCH, merge_block_id);
 
+       swap(saved_load_ids, variable_load_ids);
        writer.write_op_label(false_label_id);
        ternary.false_expr->visit(*this);
        Id false_result_id = r_expression_result_id;
        false_label_id = writer.get_current_block();
 
        writer.write_op_label(merge_block_id);
+       prune_loads(true_label_id);
        r_expression_result_id = begin_expression(OP_PHI, get_id(*ternary.type), 4);
        writer.write(true_result_id);
        writer.write(true_label_id);
@@ -1291,13 +1296,15 @@ void SpirVGenerator::visit_builtin_texture_query(FunctionCall &call, const vecto
                opcode = OP_IMAGE_QUERY_LOD;
        else if(call.name=="textureQueryLevels")
                opcode = OP_IMAGE_QUERY_LEVELS;
+       else if(call.name=="textureSamples")
+               opcode = OP_IMAGE_QUERY_SAMPLES;
        else
                throw internal_error("invalid texture query call");
 
        ImageTypeDeclaration &image_arg0 = dynamic_cast<ImageTypeDeclaration &>(*call.arguments[0]->type);
 
        Id image_id;
-       if(image_arg0.sampled)
+       if(image_arg0.sampled && opcode!=OP_IMAGE_QUERY_LOD)
        {
                Id image_type_id = get_item(image_type_ids, get_id(image_arg0));
                image_id = write_expression(OP_IMAGE, image_type_id, argument_ids[0]);
@@ -1364,15 +1371,25 @@ void SpirVGenerator::visit_builtin_texture(FunctionCall &call, const vector<Id>
 
 void SpirVGenerator::visit_builtin_texel_fetch(FunctionCall &call, const vector<Id> &argument_ids)
 {
-       if(argument_ids.size()!=3)
-               throw internal_error("invalid texelFetch call");
+       const ImageTypeDeclaration &image = dynamic_cast<const ImageTypeDeclaration &>(*call.arguments[0]->type);
+
+       Opcode opcode = OP_IMAGE_FETCH;
+
+       bool need_sample = image.multisample;
+       bool need_lod = !need_sample;
 
-       r_expression_result_id = begin_expression(OP_IMAGE_FETCH, get_id(*call.type), 4);
+       if(argument_ids.size()!=2U+need_sample+need_lod)
+               throw internal_error("invalid texture fetch call");
+
+       r_expression_result_id = begin_expression(opcode, get_id(*call.type), 2+(need_lod|need_sample)+need_lod+need_sample);
        for(unsigned i=0; i<2; ++i)
                writer.write(argument_ids[i]);
-       writer.write(2);  // Lod
-       writer.write(argument_ids.back());
-       end_expression(OP_IMAGE_FETCH);
+       if(need_lod || need_sample)
+       {
+               writer.write(need_lod*0x02 | need_sample*0x40);
+               writer.write(argument_ids.back());
+       }
+       end_expression(opcode);
 }
 
 void SpirVGenerator::visit_builtin_interpolate(FunctionCall &call, const vector<Id> &argument_ids)
@@ -1488,7 +1505,7 @@ void SpirVGenerator::visit(ImageTypeDeclaration &image)
        writer.write(image.dimensions-1);
        writer.write(image.shadow);
        writer.write(image.array);
-       writer.write(false);  // Multisample
+       writer.write(image.multisample);
        writer.write(image.sampled ? 1 : 2);
        writer.write(0);  // Format (unknown)
        writer.end_op(OP_TYPE_IMAGE);
@@ -1701,7 +1718,10 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
                writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, origin);
        }
        else if(stage->type==Stage::GEOMETRY)
+       {
                use_capability(CAP_GEOMETRY);
+               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INVOCATIONS, 1);
+       }
 
        for(const InterfaceLayout *i: interface_layouts)
        {