|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include "tgsi/tgsi_info.h"
|
|
|
|
#include "tgsi/tgsi_iterate.h"
|
|
|
|
#include "util/u_memory.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "vrend_shader.h"
|
|
|
|
extern int vrend_dump_shaders;
|
|
|
|
/*
|
|
|
|
* TODO list
|
|
|
|
* loops
|
|
|
|
* DDX/DDY/TXD
|
|
|
|
* missing opcodes
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* start convert of tgsi to glsl */
|
|
|
|
|
|
|
|
#define INTERP_PREFIX " "
|
|
|
|
|
|
|
|
int vrend_shader_use_explicit = 0;
|
|
|
|
|
|
|
|
struct vrend_shader_io {
|
|
|
|
unsigned name;
|
|
|
|
unsigned gpr;
|
|
|
|
unsigned done;
|
|
|
|
int sid;
|
|
|
|
unsigned interpolate;
|
|
|
|
boolean centroid;
|
|
|
|
unsigned first;
|
|
|
|
boolean glsl_predefined_no_emit;
|
|
|
|
boolean glsl_no_index;
|
|
|
|
boolean glsl_gl_in;
|
|
|
|
boolean override_no_wm;
|
|
|
|
boolean is_int;
|
|
|
|
char glsl_name[64];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct vrend_shader_sampler {
|
|
|
|
int tgsi_sampler_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_IMMEDIATE 1024
|
|
|
|
struct immed {
|
|
|
|
int type;
|
|
|
|
union imm {
|
|
|
|
uint32_t ui;
|
|
|
|
int32_t i;
|
|
|
|
float f;
|
|
|
|
} val[4];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dump_ctx {
|
|
|
|
struct tgsi_iterate_context iter;
|
|
|
|
struct vrend_shader_cfg *cfg;
|
|
|
|
int prog_type;
|
|
|
|
char *glsl_main;
|
|
|
|
int size;
|
|
|
|
uint instno;
|
|
|
|
|
|
|
|
int num_interps;
|
|
|
|
int num_inputs;
|
|
|
|
struct vrend_shader_io inputs[32];
|
|
|
|
int num_outputs;
|
|
|
|
struct vrend_shader_io outputs[32];
|
|
|
|
int num_system_values;
|
|
|
|
struct vrend_shader_io system_values[32];
|
|
|
|
|
|
|
|
int num_temps;
|
|
|
|
struct vrend_shader_sampler samplers[32];
|
|
|
|
uint32_t samplers_used;
|
|
|
|
int num_consts;
|
|
|
|
|
|
|
|
int num_imm;
|
|
|
|
struct immed imm[MAX_IMMEDIATE];
|
|
|
|
unsigned fragcoord_input;
|
|
|
|
|
|
|
|
int num_ubo;
|
|
|
|
int ubo_idx[32];
|
|
|
|
int ubo_sizes[32];
|
|
|
|
int num_address;
|
|
|
|
|
|
|
|
struct pipe_stream_output_info *so;
|
|
|
|
char **so_names;
|
|
|
|
bool write_so_outputs[PIPE_MAX_SO_OUTPUTS];
|
|
|
|
bool uses_cube_array;
|
|
|
|
bool uses_sampler_ms;
|
|
|
|
bool uses_sampler_buf;
|
|
|
|
bool uses_sampler_rect;
|
|
|
|
bool uses_lodq;
|
|
|
|
bool uses_txq_levels;
|
|
|
|
bool uses_tg4;
|
|
|
|
/* create a shader with lower left if upper left is primary variant
|
|
|
|
or vice versa */
|
|
|
|
uint32_t shadow_samp_mask;
|
|
|
|
boolean write_all_cbufs;
|
|
|
|
int fs_coord_origin, fs_pixel_center;
|
|
|
|
|
|
|
|
int gs_in_prim, gs_out_prim, gs_max_out_verts;
|
|
|
|
|
|
|
|
struct vrend_shader_key *key;
|
|
|
|
boolean has_ints;
|
|
|
|
boolean has_instanceid;
|
|
|
|
int indent_level;
|
|
|
|
int num_in_clip_dist;
|
|
|
|
int num_clip_dist;
|
|
|
|
|
|
|
|
int glsl_ver_required;
|
|
|
|
bool front_face_emitted;
|
|
|
|
int color_in_mask;
|
|
|
|
bool has_clipvertex;
|
|
|
|
bool has_clipvertex_so;
|
|
|
|
bool has_viewport_idx;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline const char *tgsi_proc_to_prefix(int shader_type)
|
|
|
|
{
|
|
|
|
switch (shader_type) {
|
|
|
|
case TGSI_PROCESSOR_VERTEX: return "vs";
|
|
|
|
case TGSI_PROCESSOR_FRAGMENT: return "fs";
|
|
|
|
case TGSI_PROCESSOR_GEOMETRY: return "gs";
|
|
|
|
};
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const char *prim_to_name(int prim)
|
|
|
|
{
|
|
|
|
switch (prim) {
|
|
|
|
case PIPE_PRIM_POINTS: return "points";
|
|
|
|
case PIPE_PRIM_LINES: return "lines";
|
|
|
|
case PIPE_PRIM_LINE_STRIP: return "line_strip";
|
|
|
|
case PIPE_PRIM_LINES_ADJACENCY: return "lines_adjacency";
|
|
|
|
case PIPE_PRIM_TRIANGLES: return "triangles";
|
|
|
|
case PIPE_PRIM_TRIANGLE_STRIP: return "triangle_strip";
|
|
|
|
case PIPE_PRIM_TRIANGLES_ADJACENCY: return "triangles_adjacency";
|
|
|
|
default: return "UNKNOWN";
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int gs_input_prim_to_size(int prim)
|
|
|
|
{
|
|
|
|
switch (prim) {
|
|
|
|
case PIPE_PRIM_POINTS: return 1;
|
|
|
|
case PIPE_PRIM_LINES: return 2;
|
|
|
|
case PIPE_PRIM_LINES_ADJACENCY: return 4;
|
|
|
|
case PIPE_PRIM_TRIANGLES: return 3;
|
|
|
|
case PIPE_PRIM_TRIANGLES_ADJACENCY: return 6;
|
|
|
|
default: return -1;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline boolean fs_emit_layout(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
if (ctx->fs_pixel_center)
|
|
|
|
return TRUE;
|
|
|
|
/* if coord origin is 0 and invert is 0 - emit origin_upper_left,
|
|
|
|
if coord_origin is 0 and invert is 1 - emit nothing (lower)
|
|
|
|
if coord origin is 1 and invert is 0 - emit nothing (lower)
|
|
|
|
if coord_origin is 1 and invert is 1 - emit origin upper left */
|
|
|
|
if (!(ctx->fs_coord_origin ^ ctx->key->invert_fs_origin))
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *strcat_realloc(char *str, const char *catstr)
|
|
|
|
{
|
|
|
|
str = realloc(str, strlen(str) + strlen(catstr) + 1);
|
|
|
|
if (!str)
|
|
|
|
return NULL;
|
|
|
|
strcat(str, catstr);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *add_str_to_glsl_main(struct dump_ctx *ctx, char *buf)
|
|
|
|
{
|
|
|
|
ctx->glsl_main = strcat_realloc(ctx->glsl_main, buf);
|
|
|
|
return ctx->glsl_main;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
iter_declaration(struct tgsi_iterate_context *iter,
|
|
|
|
struct tgsi_full_declaration *decl )
|
|
|
|
{
|
|
|
|
struct dump_ctx *ctx = (struct dump_ctx *)iter;
|
|
|
|
int i;
|
|
|
|
int color_offset = 0;
|
|
|
|
char *name_prefix = "";
|
|
|
|
bool add_two_side = false;
|
|
|
|
|
|
|
|
switch (decl->Declaration.File) {
|
|
|
|
case TGSI_FILE_INPUT:
|
|
|
|
i = ctx->num_inputs++;
|
|
|
|
ctx->inputs[i].name = decl->Semantic.Name;
|
|
|
|
ctx->inputs[i].sid = decl->Semantic.Index;
|
|
|
|
ctx->inputs[i].interpolate = decl->Interp.Interpolate;
|
|
|
|
ctx->inputs[i].first = decl->Range.First;
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = FALSE;
|
|
|
|
ctx->inputs[i].glsl_no_index = FALSE;
|
|
|
|
ctx->inputs[i].override_no_wm = FALSE;
|
|
|
|
ctx->inputs[i].glsl_gl_in = FALSE;
|
|
|
|
|
|
|
|
switch (ctx->inputs[i].name) {
|
|
|
|
case TGSI_SEMANTIC_COLOR:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (ctx->glsl_ver_required < 140) {
|
|
|
|
if (decl->Semantic.Index == 0)
|
|
|
|
name_prefix = "gl_Color";
|
|
|
|
else if (decl->Semantic.Index == 1)
|
|
|
|
name_prefix = "gl_SecondaryColor";
|
|
|
|
else
|
|
|
|
fprintf(stderr, "got illegal color semantic index %d\n", decl->Semantic.Index);
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
} else {
|
|
|
|
if (ctx->key->color_two_side) {
|
|
|
|
int j = ctx->num_inputs++;
|
|
|
|
ctx->inputs[j].name = TGSI_SEMANTIC_BCOLOR;
|
|
|
|
ctx->inputs[j].sid = decl->Semantic.Index;
|
|
|
|
ctx->inputs[j].interpolate = decl->Interp.Interpolate;
|
|
|
|
ctx->inputs[j].first = decl->Range.First;
|
|
|
|
ctx->inputs[j].glsl_predefined_no_emit = FALSE;
|
|
|
|
ctx->inputs[j].glsl_no_index = FALSE;
|
|
|
|
ctx->inputs[j].override_no_wm = FALSE;
|
|
|
|
|
|
|
|
ctx->color_in_mask |= (1 << decl->Semantic.Index);
|
|
|
|
|
|
|
|
if (ctx->front_face_emitted == false) {
|
|
|
|
int k = ctx->num_inputs++;
|
|
|
|
ctx->inputs[k].name = TGSI_SEMANTIC_FACE;
|
|
|
|
ctx->inputs[k].sid = 0;
|
|
|
|
ctx->inputs[k].interpolate = 0;
|
|
|
|
ctx->inputs[k].centroid = 0;
|
|
|
|
ctx->inputs[k].first = 0;
|
|
|
|
ctx->inputs[k].override_no_wm = FALSE;
|
|
|
|
ctx->inputs[k].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[k].glsl_no_index = TRUE;
|
|
|
|
}
|
|
|
|
add_two_side = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
name_prefix = "ex";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case TGSI_SEMANTIC_PRIMID:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
name_prefix = "gl_PrimitiveIDIn";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->inputs[i].override_no_wm = TRUE;
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
break;
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
name_prefix = "gl_PrimitiveID";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->glsl_ver_required = 150;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_PSIZE:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
name_prefix = "gl_PointSize";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->inputs[i].override_no_wm = TRUE;
|
|
|
|
ctx->inputs[i].glsl_gl_in = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_CLIPDIST:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
name_prefix = "gl_ClipDistance";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->inputs[i].glsl_gl_in = TRUE;
|
|
|
|
ctx->num_in_clip_dist += 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_POSITION:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
name_prefix = "gl_Position";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->inputs[i].glsl_gl_in = TRUE;
|
|
|
|
break;
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
name_prefix = "gl_FragCoord";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fallthrough for vertex shader */
|
|
|
|
case TGSI_SEMANTIC_FACE:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (ctx->front_face_emitted) {
|
|
|
|
ctx->num_inputs--;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
name_prefix = "gl_FrontFacing";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->front_face_emitted = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_GENERIC:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (ctx->key->coord_replace & (1 << ctx->inputs[i].sid)) {
|
|
|
|
name_prefix = "vec4(gl_PointCoord, 0.0, 1.0)";
|
|
|
|
ctx->inputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->inputs[i].glsl_no_index = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT ||
|
|
|
|
iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
|
|
|
|
ctx->key->gs_present)
|
|
|
|
name_prefix = "out";
|
|
|
|
else
|
|
|
|
name_prefix = "ex";
|
|
|
|
} else
|
|
|
|
name_prefix = "in";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->inputs[i].glsl_no_index)
|
|
|
|
snprintf(ctx->inputs[i].glsl_name, 64, "%s", name_prefix);
|
|
|
|
else {
|
|
|
|
if (ctx->inputs[i].name == TGSI_SEMANTIC_FOG)
|
|
|
|
snprintf(ctx->inputs[i].glsl_name, 64, "%s_f%d", name_prefix, ctx->inputs[i].sid);
|
|
|
|
else if (ctx->inputs[i].name == TGSI_SEMANTIC_COLOR)
|
|
|
|
snprintf(ctx->inputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->inputs[i].sid);
|
|
|
|
else if (ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC)
|
|
|
|
snprintf(ctx->inputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->inputs[i].sid);
|
|
|
|
else
|
|
|
|
snprintf(ctx->inputs[i].glsl_name, 64, "%s_%d", name_prefix, ctx->inputs[i].first);
|
|
|
|
}
|
|
|
|
if (add_two_side) {
|
|
|
|
snprintf(ctx->inputs[i + 1].glsl_name, 64, "%s_bc%d", name_prefix, ctx->inputs[i + 1].sid);
|
|
|
|
if (!ctx->front_face_emitted) {
|
|
|
|
snprintf(ctx->inputs[i + 2].glsl_name, 64, "%s", "gl_FrontFacing");
|
|
|
|
ctx->front_face_emitted = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_OUTPUT:
|
|
|
|
i = ctx->num_outputs++;
|
|
|
|
ctx->outputs[i].name = decl->Semantic.Name;
|
|
|
|
ctx->outputs[i].sid = decl->Semantic.Index;
|
|
|
|
ctx->outputs[i].interpolate = decl->Interp.Interpolate;
|
|
|
|
ctx->outputs[i].first = decl->Range.First;
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = FALSE;
|
|
|
|
ctx->outputs[i].glsl_no_index = FALSE;
|
|
|
|
ctx->outputs[i].override_no_wm = FALSE;
|
|
|
|
ctx->outputs[i].is_int = FALSE;
|
|
|
|
|
|
|
|
switch (ctx->outputs[i].name) {
|
|
|
|
case TGSI_SEMANTIC_POSITION:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX ||
|
|
|
|
iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
if (ctx->outputs[i].first > 0)
|
|
|
|
fprintf(stderr,"Illegal position input\n");
|
|
|
|
name_prefix = "gl_Position";
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (ctx->outputs[i].first > 0)
|
|
|
|
fprintf(stderr,"Illegal position input\n");
|
|
|
|
name_prefix = "gl_FragDepth";
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGSI_SEMANTIC_CLIPDIST:
|
|
|
|
name_prefix = "gl_ClipDistance";
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->num_clip_dist += 4;
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX &&
|
|
|
|
ctx->key->gs_present)
|
|
|
|
ctx->glsl_ver_required = 150;
|
|
|
|
break;
|
|
|
|
case TGSI_SEMANTIC_CLIPVERTEX:
|
|
|
|
name_prefix = "gl_ClipVertex";
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
if (ctx->glsl_ver_required >= 140)
|
|
|
|
ctx->has_clipvertex = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TGSI_SEMANTIC_COLOR:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
|
|
|
|
if (ctx->glsl_ver_required < 140) {
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
if (ctx->outputs[i].sid == 0)
|
|
|
|
name_prefix = "gl_FrontColor";
|
|
|
|
else if (ctx->outputs[i].sid == 1)
|
|
|
|
name_prefix = "gl_FrontSecondaryColor";
|
|
|
|
} else
|
|
|
|
name_prefix = "ex";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TGSI_SEMANTIC_BCOLOR:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
|
|
|
|
if (ctx->glsl_ver_required < 140) {
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
if (ctx->outputs[i].sid == 0)
|
|
|
|
name_prefix = "gl_BackColor";
|
|
|
|
else if (ctx->outputs[i].sid == 1)
|
|
|
|
name_prefix = "gl_BackSecondaryColor";
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
name_prefix = "ex";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_PSIZE:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
name_prefix = "gl_PointSize";
|
|
|
|
break;
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
name_prefix = "gl_PointSize";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_LAYER:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
ctx->outputs[i].is_int = TRUE;
|
|
|
|
name_prefix = "gl_Layer";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_PRIMID:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
ctx->outputs[i].is_int = TRUE;
|
|
|
|
name_prefix = "gl_PrimitiveID";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_VIEWPORT_INDEX:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->outputs[i].glsl_no_index = TRUE;
|
|
|
|
ctx->outputs[i].override_no_wm = TRUE;
|
|
|
|
ctx->outputs[i].is_int = TRUE;
|
|
|
|
name_prefix = "gl_ViewportIndex";
|
|
|
|
if (ctx->glsl_ver_required >= 140)
|
|
|
|
ctx->has_viewport_idx = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TGSI_SEMANTIC_GENERIC:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX)
|
|
|
|
if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
|
|
|
|
color_offset = -1;
|
|
|
|
default:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX)
|
|
|
|
name_prefix = "ex";
|
|
|
|
else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT)
|
|
|
|
name_prefix = "fsout";
|
|
|
|
else
|
|
|
|
name_prefix = "out";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->outputs[i].glsl_no_index)
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s", name_prefix);
|
|
|
|
else {
|
|
|
|
if (ctx->outputs[i].name == TGSI_SEMANTIC_FOG)
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s_f%d", name_prefix, ctx->outputs[i].sid);
|
|
|
|
else if (ctx->outputs[i].name == TGSI_SEMANTIC_COLOR)
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->outputs[i].sid);
|
|
|
|
else if (ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s_bc%d", name_prefix, ctx->outputs[i].sid);
|
|
|
|
else if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->outputs[i].sid);
|
|
|
|
else
|
|
|
|
snprintf(ctx->outputs[i].glsl_name, 64, "%s_%d", name_prefix, ctx->outputs[i].first + color_offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_TEMPORARY:
|
|
|
|
if (decl->Range.Last) {
|
|
|
|
if (decl->Range.Last + 1 > ctx->num_temps)
|
|
|
|
ctx->num_temps = decl->Range.Last + 1;
|
|
|
|
} else
|
|
|
|
ctx->num_temps++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_SAMPLER:
|
|
|
|
ctx->samplers_used |= (1 << decl->Range.Last);
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_CONSTANT:
|
|
|
|
if (decl->Declaration.Dimension) {
|
|
|
|
if (ctx->num_ubo >= ARRAY_SIZE(ctx->ubo_idx)) {
|
|
|
|
fprintf(stderr, "Number of uniforms exceeded, max is %lu\n", ARRAY_SIZE(ctx->ubo_idx));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ctx->ubo_idx[ctx->num_ubo] = decl->Dim.Index2D;
|
|
|
|
ctx->ubo_sizes[ctx->num_ubo] = decl->Range.Last + 1;
|
|
|
|
ctx->num_ubo++;
|
|
|
|
} else {
|
|
|
|
if (decl->Range.Last) {
|
|
|
|
if (decl->Range.Last + 1 > ctx->num_consts)
|
|
|
|
ctx->num_consts = decl->Range.Last + 1;
|
|
|
|
} else
|
|
|
|
ctx->num_consts++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_ADDRESS:
|
|
|
|
ctx->num_address = 1;
|
|
|
|
break;
|
|
|
|
case TGSI_FILE_SYSTEM_VALUE:
|
|
|
|
i = ctx->num_system_values++;
|
|
|
|
ctx->system_values[i].name = decl->Semantic.Name;
|
|
|
|
ctx->system_values[i].sid = decl->Semantic.Index;
|
|
|
|
ctx->system_values[i].glsl_predefined_no_emit = TRUE;
|
|
|
|
ctx->system_values[i].glsl_no_index = TRUE;
|
|
|
|
ctx->system_values[i].override_no_wm = TRUE;
|
|
|
|
ctx->system_values[i].first = decl->Range.First;
|
|
|
|
if (decl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) {
|
|
|
|
name_prefix = "gl_InstanceID";
|
|
|
|
ctx->has_instanceid = TRUE;
|
|
|
|
} else if (decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) {
|
|
|
|
name_prefix = "gl_VertexID";
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "unsupported system value %d\n", decl->Semantic.Name);
|
|
|
|
name_prefix = "unknown";
|
|
|
|
}
|
|
|
|
snprintf(ctx->system_values[i].glsl_name, 64, "%s", name_prefix);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr,"unsupported file %d declaration\n", decl->Declaration.File);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
iter_property(struct tgsi_iterate_context *iter,
|
|
|
|
struct tgsi_full_property *prop)
|
|
|
|
{
|
|
|
|
struct dump_ctx *ctx = (struct dump_ctx *) iter;
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
|
|
|
|
if (prop->u[0].Data == 1)
|
|
|
|
ctx->write_all_cbufs = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COORD_ORIGIN) {
|
|
|
|
ctx->fs_coord_origin = prop->u[0].Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COORD_PIXEL_CENTER) {
|
|
|
|
ctx->fs_pixel_center = prop->u[0].Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_GS_INPUT_PRIM) {
|
|
|
|
ctx->gs_in_prim = prop->u[0].Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_GS_OUTPUT_PRIM) {
|
|
|
|
ctx->gs_out_prim = prop->u[0].Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->Property.PropertyName == TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES) {
|
|
|
|
ctx->gs_max_out_verts = prop->u[0].Data;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
iter_immediate(
|
|
|
|
struct tgsi_iterate_context *iter,
|
|
|
|
struct tgsi_full_immediate *imm )
|
|
|
|
{
|
|
|
|
struct dump_ctx *ctx = (struct dump_ctx *) iter;
|
|
|
|
int i;
|
|
|
|
int first = ctx->num_imm;
|
|
|
|
|
|
|
|
if (first >= ARRAY_SIZE(ctx->imm)) {
|
|
|
|
fprintf(stderr, "Number of immediates exceeded, max is: %lu\n", ARRAY_SIZE(ctx->imm));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->imm[first].type = imm->Immediate.DataType;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (imm->Immediate.DataType == TGSI_IMM_FLOAT32) {
|
|
|
|
ctx->imm[first].val[i].f = imm->u[i].Float;
|
|
|
|
} else if (imm->Immediate.DataType == TGSI_IMM_UINT32) {
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
ctx->imm[first].val[i].ui = imm->u[i].Uint;
|
|
|
|
} else if (imm->Immediate.DataType == TGSI_IMM_INT32) {
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
ctx->imm[first].val[i].i = imm->u[i].Int;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ctx->num_imm++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char get_swiz_char(int swiz)
|
|
|
|
{
|
|
|
|
switch(swiz){
|
|
|
|
case TGSI_SWIZZLE_X: return 'x';
|
|
|
|
case TGSI_SWIZZLE_Y: return 'y';
|
|
|
|
case TGSI_SWIZZLE_Z: return 'z';
|
|
|
|
case TGSI_SWIZZLE_W: return 'w';
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_cbuf_writes(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
int i;
|
|
|
|
char *sret;
|
|
|
|
|
|
|
|
for (i = 1; i < 8; i++) {
|
|
|
|
snprintf(buf, 255, "fsout_c%d = fsout_c0;\n", i);
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *atests[PIPE_FUNC_ALWAYS + 1] = {
|
|
|
|
"false",
|
|
|
|
"%s < %f",
|
|
|
|
"%s == %f",
|
|
|
|
"%s <= %f",
|
|
|
|
"%s > %f",
|
|
|
|
"%s != %f",
|
|
|
|
"%s >= %f",
|
|
|
|
"true",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int emit_alpha_test(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
char comp_buf[128];
|
|
|
|
char *sret;
|
|
|
|
snprintf(comp_buf, 128, atests[ctx->key->alpha_test], "fsout_c0.w", ctx->key->alpha_ref_val);
|
|
|
|
|
|
|
|
snprintf(buf, 255, "if (!(%s)) {\n\tdiscard;\n}\n", comp_buf);
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_pstipple_pass(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
char *sret;
|
|
|
|
snprintf(buf, 255, "stip_temp = texture(pstipple_sampler, vec2(gl_FragCoord.x / 32, gl_FragCoord.y / 32)).x;\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
snprintf(buf, 255, "if (stip_temp > 0) {\n\tdiscard;\n}\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
return sret ? 0 : ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_color_select(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
char *sret = NULL;
|
|
|
|
|
|
|
|
if (!ctx->key->color_two_side || !(ctx->color_in_mask & 0x3))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ctx->color_in_mask & 1) {
|
|
|
|
snprintf(buf, 255, "realcolor0 = gl_FrontFacing ? ex_c0 : ex_bc0;\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
}
|
|
|
|
if (ctx->color_in_mask & 2) {
|
|
|
|
snprintf(buf, 255, "realcolor1 = gl_FrontFacing ? ex_c1 : ex_bc1;\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
}
|
|
|
|
return sret ? 0 : ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_prescale(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
char *sret;
|
|
|
|
|
|
|
|
snprintf(buf, 255, "gl_Position.y = gl_Position.y * winsys_adjust.y;\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
snprintf(buf, 255, "gl_Position.z = dot(gl_Position, vec4(0.0, 0.0, winsys_adjust.zw));\n");
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_so_movs(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
int i, j;
|
|
|
|
char outtype[15] = {0};
|
|
|
|
char writemask[6];
|
|
|
|
char *sret;
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->so->num_outputs; i++) {
|
|
|
|
if (ctx->so->output[i].start_component != 0) {
|
|
|
|
int wm_idx = 0;
|
|
|
|
writemask[wm_idx++] = '.';
|
|
|
|
for (j = 0; j < ctx->so->output[i].num_components; j++) {
|
|
|
|
unsigned idx = ctx->so->output[i].start_component + j;
|
|
|
|
if (idx >= 4)
|
|
|
|
break;
|
|
|
|
if (idx <= 2)
|
|
|
|
writemask[wm_idx++] = 'x' + idx;
|
|
|
|
else
|
|
|
|
writemask[wm_idx++] = 'w';
|
|
|
|
}
|
|
|
|
writemask[wm_idx] = '\0';
|
|
|
|
} else
|
|
|
|
writemask[0] = 0;
|
|
|
|
|
|
|
|
if (ctx->so->output[i].num_components == 4 && writemask[0] == 0 && !(ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPDIST) && !(ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_POSITION)) {
|
|
|
|
if (ctx->so->output[i].register_index > ctx->num_outputs)
|
|
|
|
ctx->so_names[i] = NULL;
|
|
|
|
else if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPVERTEX && ctx->has_clipvertex) {
|
|
|
|
ctx->so_names[i] = strdup("clipv_tmp");
|
|
|
|
ctx->has_clipvertex_so = true;
|
|
|
|
} else
|
|
|
|
ctx->so_names[i] = strdup(ctx->outputs[ctx->so->output[i].register_index].glsl_name);
|
|
|
|
ctx->write_so_outputs[i] = false;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
char ntemp[8];
|
|
|
|
snprintf(ntemp, 8, "tfout%d", i);
|
|
|
|
ctx->so_names[i] = strdup(ntemp);
|
|
|
|
ctx->write_so_outputs[i] = true;
|
|
|
|
}
|
|
|
|
if (ctx->so->output[i].num_components == 1) {
|
|
|
|
if (ctx->outputs[ctx->so->output[i].register_index].is_int)
|
|
|
|
snprintf(outtype, 15, "intBitsToFloat");
|
|
|
|
else
|
|
|
|
snprintf(outtype, 15, "float");
|
|
|
|
} else
|
|
|
|
snprintf(outtype, 15, "vec%d", ctx->so->output[i].num_components);
|
|
|
|
|
|
|
|
if (ctx->so->output[i].register_index >= 255)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
buf[0] = 0;
|
|
|
|
if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPDIST) {
|
|
|
|
snprintf(buf, 255, "tfout%d = %s(clip_dist_temp[%d]%s);\n", i, outtype, ctx->outputs[ctx->so->output[i].register_index].sid,
|
|
|
|
writemask);
|
|
|
|
} else {
|
|
|
|
if (ctx->write_so_outputs[i])
|
|
|
|
snprintf(buf, 255, "tfout%d = %s(%s%s);\n", i, outtype, ctx->outputs[ctx->so->output[i].register_index].glsl_name, writemask);
|
|
|
|
}
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int emit_clip_dist_movs(struct dump_ctx *ctx)
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
int i;
|
|
|
|
char *sret;
|
|
|
|
|
|
|
|
if (ctx->num_clip_dist == 0 && ctx->key->clip_plane_enable) {
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
snprintf(buf, 255, "gl_ClipDistance[%d] = dot(%s, clipp[%d]);\n", i, ctx->has_clipvertex ? "clipv_tmp" : "gl_Position", i);
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (i = 0; i < ctx->num_clip_dist; i++) {
|
|
|
|
int clipidx = i < 4 ? 0 : 1;
|
|
|
|
char swiz = i & 3;
|
|
|
|
char wm = 0;
|
|
|
|
switch (swiz) {
|
|
|
|
case 0: wm = 'x'; break;
|
|
|
|
case 1: wm = 'y'; break;
|
|
|
|
case 2: wm = 'z'; break;
|
|
|
|
case 3: wm = 'w'; break;
|
|
|
|
}
|
|
|
|
snprintf(buf, 255, "gl_ClipDistance[%d] = clip_dist_temp[%d].%c;\n",
|
|
|
|
i, clipidx, wm);
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define emit_arit_op2(op) snprintf(buf, 255, "%s = %s(%s((%s %s %s))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], op, srcs[1], writemask)
|
|
|
|
#define emit_op1(op) snprintf(buf, 255, "%s = %s(%s(%s(%s))%s);\n", dsts[0], dstconv, dtypeprefix, op, srcs[0], writemask)
|
|
|
|
#define emit_compare(op) snprintf(buf, 255, "%s = %s(%s((%s(%s(%s), %s(%s))))%s);\n", dsts[0], dstconv, dtypeprefix, op, svec4, srcs[0], svec4, srcs[1], writemask)
|
|
|
|
|
|
|
|
#define emit_ucompare(op) snprintf(buf, 255, "%s = %s(uintBitsToFloat(%s(%s(%s(%s), %s(%s))%s) * %s(0xffffffff)));\n", dsts[0], dstconv, udstconv, op, svec4, srcs[0], svec4, srcs[1], writemask, udstconv)
|
|
|
|
|
|
|
|
static int emit_buf(struct dump_ctx *ctx, char *buf)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *sret;
|
|
|
|
for (i = 0; i < ctx->indent_level; i++) {
|
|
|
|
sret = add_str_to_glsl_main(ctx, "\t");
|
|
|
|
if (!sret)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
sret = add_str_to_glsl_main(ctx, buf);
|
|
|
|
return sret ? 0 : ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EMIT_BUF_WITH_RET(ctx, buf) do { \
|
|
|
|
int ret = emit_buf((ctx), (buf)); \
|
|
|
|
if (ret) return FALSE; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
static int translate_tex(struct dump_ctx *ctx,
|
|
|
|
struct tgsi_full_instruction *inst,
|
|
|
|
int sreg_index,
|
|
|
|
char srcs[4][255],
|
|
|
|
char dsts[3][255],
|
|
|
|
const char *writemask,
|
|
|
|
const char *dstconv,
|
|
|
|
const char *dtypeprefix)
|
|
|
|
{
|
|
|
|
char *twm, *gwm = NULL, *txfi;
|
|
|
|
bool is_shad = false;
|
|
|
|
char buf[512];
|
|
|
|
char offbuf[128] = {0};
|
|
|
|
char bias[128] = {0};
|
|
|
|
int sampler_index;
|
|
|
|
char *tex_ext;
|
|
|
|
|
|
|
|
ctx->samplers[sreg_index].tgsi_sampler_type = inst->Texture.Texture;
|
|
|
|
|
|
|
|
switch (inst->Texture.Texture) {
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
|
|
|
|
is_shad = true;
|
|
|
|
case TGSI_TEXTURE_CUBE_ARRAY:
|
|
|
|
ctx->uses_cube_array = true;
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_2D_MSAA:
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY_MSAA:
|
|
|
|
ctx->uses_sampler_ms = true;
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_BUFFER:
|
|
|
|
ctx->uses_sampler_buf = true;
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_SHADOWRECT:
|
|
|
|
is_shad = true;
|
|
|
|
case TGSI_TEXTURE_RECT:
|
|
|
|
ctx->uses_sampler_rect = true;
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_SHADOW1D:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D:
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D_ARRAY:
|
|
|
|
is_shad = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->cfg->glsl_version >= 140)
|
|
|
|
if (ctx->uses_sampler_rect || ctx->uses_sampler_buf)
|
|
|
|
ctx->glsl_ver_required = 140;
|
|
|
|
|
|
|
|
sampler_index = 1;
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_LODQ)
|
|
|
|
ctx->uses_lodq = true;
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) {
|
|
|
|
/* no lod parameter for txq for these */
|
|
|
|
if (inst->Texture.Texture != TGSI_TEXTURE_RECT &&
|
|
|
|
inst->Texture.Texture != TGSI_TEXTURE_SHADOWRECT &&
|
|
|
|
inst->Texture.Texture != TGSI_TEXTURE_BUFFER &&
|
|
|
|
inst->Texture.Texture != TGSI_TEXTURE_2D_MSAA &&
|
|
|
|
inst->Texture.Texture != TGSI_TEXTURE_2D_ARRAY_MSAA)
|
|
|
|
snprintf(bias, 128, ", int(%s.w)", srcs[0]);
|
|
|
|
|
|
|
|
/* need to emit a textureQueryLevels */
|
|
|
|
if (inst->Dst[0].Register.WriteMask & 0x8) {
|
|
|
|
ctx->uses_txq_levels = true;
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(textureQueryLevels(%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[sampler_index]);
|
|
|
|
return emit_buf(ctx, buf);
|
|
|
|
} else {
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(textureSize(%s%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[sampler_index], bias);
|
|
|
|
return emit_buf(ctx, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (inst->Texture.Texture) {
|
|
|
|
case TGSI_TEXTURE_1D:
|
|
|
|
case TGSI_TEXTURE_BUFFER:
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXP)
|
|
|
|
twm = "";
|
|
|
|
else
|
|
|
|
twm = ".x";
|
|
|
|
txfi = "int";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_1D_ARRAY:
|
|
|
|
twm = ".xy";
|
|
|
|
txfi = "ivec2";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_2D:
|
|
|
|
case TGSI_TEXTURE_RECT:
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXP)
|
|
|
|
twm = "";
|
|
|
|
else
|
|
|
|
twm = ".xy";
|
|
|
|
txfi = "ivec2";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_SHADOW1D:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOWRECT:
|
|
|
|
case TGSI_TEXTURE_3D:
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXP)
|
|
|
|
twm = "";
|
|
|
|
else
|
|
|
|
twm = ".xyz";
|
|
|
|
txfi = "ivec3";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_CUBE:
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY:
|
|
|
|
twm = ".xyz";
|
|
|
|
txfi = "ivec3";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_2D_MSAA:
|
|
|
|
twm = ".xy";
|
|
|
|
txfi = "ivec2";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY_MSAA:
|
|
|
|
twm = ".xyz";
|
|
|
|
txfi = "ivec3";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
|
|
|
|
case TGSI_TEXTURE_CUBE_ARRAY:
|
|
|
|
default:
|
|
|
|
twm = "";
|
|
|
|
txfi = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
|
|
|
|
switch (inst->Texture.Texture) {
|
|
|
|
case TGSI_TEXTURE_1D:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D:
|
|
|
|
case TGSI_TEXTURE_1D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D_ARRAY:
|
|
|
|
gwm = ".x";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_2D:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D:
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_RECT:
|
|
|
|
case TGSI_TEXTURE_SHADOWRECT:
|
|
|
|
gwm = ".xy";
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_3D:
|
|
|
|
case TGSI_TEXTURE_CUBE:
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE:
|
|
|
|
case TGSI_TEXTURE_CUBE_ARRAY:
|
|
|
|
gwm = ".xyz";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
gwm = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXB2 || inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || inst->Instruction.Opcode == TGSI_OPCODE_TEX2) {
|
|
|
|
sampler_index = 2;
|
|
|
|
if (inst->Instruction.Opcode != TGSI_OPCODE_TEX2)
|
|
|
|
snprintf(bias, 64, ", %s.x", srcs[1]);
|
|
|
|
else if (inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY)
|
|
|
|
snprintf(bias, 64, ", float(%s)", srcs[1]);
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TXB || inst->Instruction.Opcode == TGSI_OPCODE_TXL)
|
|
|
|
snprintf(bias, 64, ", %s.w", srcs[0]);
|
|
|
|
else if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) {
|
|
|
|
if (inst->Texture.Texture == TGSI_TEXTURE_1D ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_2D ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_3D ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_1D_ARRAY ||
|
|
|
|
inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY) {
|
|
|
|
snprintf(bias, 64, ", int(%s.w)", srcs[0]);
|
|
|
|
}
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
|
|
|
|
snprintf(bias, 128, ", %s%s, %s%s", srcs[1], gwm, srcs[2], gwm);
|
|
|
|
sampler_index = 3;
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TG4) {
|
|
|
|
sampler_index = 2;
|
|
|
|
ctx->uses_tg4 = true;
|
|
|
|
} else
|
|
|
|
bias[0] = 0;
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_LODQ) {
|
|
|
|
tex_ext = "QueryLOD";
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TXP) {
|
|
|
|
if (inst->Texture.Texture == TGSI_TEXTURE_CUBE || inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_1D_ARRAY)
|
|
|
|
tex_ext = "";
|
|
|
|
else if (inst->Texture.NumOffsets == 1)
|
|
|
|
tex_ext = "ProjOffset";
|
|
|
|
else
|
|
|
|
tex_ext = "Proj";
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TXL || inst->Instruction.Opcode == TGSI_OPCODE_TXL2) {
|
|
|
|
if (inst->Texture.NumOffsets == 1)
|
|
|
|
tex_ext = "LodOffset";
|
|
|
|
else
|
|
|
|
tex_ext = "Lod";
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
|
|
|
|
if (inst->Texture.NumOffsets == 1)
|
|
|
|
tex_ext = "GradOffset";
|
|
|
|
else
|
|
|
|
tex_ext = "Grad";
|
|
|
|
} else if (inst->Instruction.Opcode == TGSI_OPCODE_TG4) {
|
|
|
|
if (inst->Texture.NumOffsets == 1)
|
|
|
|
tex_ext = "GatherOffset";
|
|
|
|
else
|
|
|
|
tex_ext = "Gather";
|
|
|
|
} else {
|
|
|
|
if (inst->Texture.NumOffsets == 1)
|
|
|
|
tex_ext = "Offset";
|
|
|
|
else
|
|
|
|
tex_ext = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inst->Texture.NumOffsets == 1) {
|
|
|
|
struct immed *imd = &ctx->imm[(inst->TexOffsets[0].Index)];
|
|
|
|
switch (inst->Texture.Texture) {
|
|
|
|
case TGSI_TEXTURE_1D:
|
|
|
|
case TGSI_TEXTURE_1D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D:
|
|
|
|
case TGSI_TEXTURE_SHADOW1D_ARRAY:
|
|
|
|
snprintf(offbuf, 25, ", int(%d)", imd->val[inst->TexOffsets[0].SwizzleX].i);
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_RECT:
|
|
|
|
case TGSI_TEXTURE_SHADOWRECT:
|
|
|
|
case TGSI_TEXTURE_2D:
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D:
|
|
|
|
case TGSI_TEXTURE_SHADOW2D_ARRAY:
|
|
|
|
snprintf(offbuf, 25, ", ivec2(%d, %d)", imd->val[inst->TexOffsets[0].SwizzleX].i, imd->val[inst->TexOffsets[0].SwizzleY].i);
|
|
|
|
break;
|
|
|
|
case TGSI_TEXTURE_3D:
|
|
|
|
snprintf(offbuf, 25, ", ivec3(%d, %d, %d)", imd->val[inst->TexOffsets[0].SwizzleX].i, imd->val[inst->TexOffsets[0].SwizzleY].i,
|
|
|
|
imd->val[inst->TexOffsets[0].SwizzleZ].i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXL || inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
|
|
|
|
char tmp[128];
|
|
|
|
strcpy(tmp, offbuf);
|
|
|
|
strcpy(offbuf, bias);
|
|
|
|
strcpy(bias, tmp);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) {
|
|
|
|
snprintf(buf, 255, "%s = %s(texelFetch%s(%s, %s(%s%s)%s%s)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], txfi, srcs[0], twm, bias, offbuf, ctx->outputs[0].override_no_wm ? "" : writemask);
|
|
|
|
} else if (ctx->cfg->glsl_version < 140 && ctx->uses_sampler_rect) {
|
|
|
|
/* rect is special in GLSL 1.30 */
|
|
|
|
if (inst->Texture.Texture == TGSI_TEXTURE_RECT)
|
|
|
|
snprintf(buf, 255, "%s = texture2DRect(%s, %s.xy)%s;\n", dsts[0], srcs[sampler_index], srcs[0], writemask);
|
|
|
|
else if (inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT)
|
|
|
|
snprintf(buf, 255, "%s = shadow2DRect(%s, %s.xyz)%s;\n", dsts[0], srcs[sampler_index], srcs[0], writemask);
|
|
|
|
} else if (is_shad) { /* TGSI returns 1.0 in alpha */
|
|
|
|
const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
const struct tgsi_full_src_register *src = &inst->Src[sampler_index];
|
|
|
|
snprintf(buf, 255, "%s = %s(vec4(vec4(texture%s(%s, %s%s%s%s)) * %sshadmask%d + %sshadadd%d)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], srcs[0], twm, offbuf, bias, cname, src->Register.Index, cname, src->Register.Index, writemask);
|
|
|
|
} else
|
|
|
|
snprintf(buf, 255, "%s = %s(texture%s(%s, %s%s%s%s)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], srcs[0], twm, offbuf, bias, ctx->outputs[0].override_no_wm ? "" : writemask);
|
|
|
|
return emit_buf(ctx, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
iter_instruction(struct tgsi_iterate_context *iter,
|
|
|
|
struct tgsi_full_instruction *inst)
|
|
|
|
{
|
|
|
|
struct dump_ctx *ctx = (struct dump_ctx *)iter;
|
|
|
|
char srcs[4][255], dsts[3][255], buf[512];
|
|
|
|
uint instno = ctx->instno++;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int sreg_index = 0;
|
|
|
|
char dstconv[32] = {0};
|
|
|
|
char udstconv[32] = {0};
|
|
|
|
char writemask[6] = {0};
|
|
|
|
enum tgsi_opcode_type dtype = tgsi_opcode_infer_dst_type(inst->Instruction.Opcode);
|
|
|
|
enum tgsi_opcode_type stype = tgsi_opcode_infer_src_type(inst->Instruction.Opcode);
|
|
|
|
char *dtypeprefix="", *stypeprefix = "", *svec4 = "vec4";
|
|
|
|
bool stprefix = false;
|
|
|
|
bool override_no_wm[4];
|
|
|
|
char *sret;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (ctx->prog_type == -1)
|
|
|
|
ctx->prog_type = iter->processor.Processor;
|
|
|
|
if (dtype == TGSI_TYPE_SIGNED || dtype == TGSI_TYPE_UNSIGNED ||
|
|
|
|
stype == TGSI_TYPE_SIGNED || stype == TGSI_TYPE_UNSIGNED)
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
|
|
|
|
if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) {
|
|
|
|
dtypeprefix = "intBitsToFloat";
|
|
|
|
} else {
|
|
|
|
switch (dtype) {
|
|
|
|
case TGSI_TYPE_UNSIGNED:
|
|
|
|
dtypeprefix = "uintBitsToFloat";
|
|
|
|
break;
|
|
|
|
case TGSI_TYPE_SIGNED:
|
|
|
|
dtypeprefix = "intBitsToFloat";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (stype) {
|
|
|
|
case TGSI_TYPE_UNSIGNED:
|
|
|
|
stypeprefix = "floatBitsToUint";
|
|
|
|
svec4 = "uvec4";
|
|
|
|
stprefix = true;
|
|
|
|
break;
|
|
|
|
case TGSI_TYPE_SIGNED:
|
|
|
|
stypeprefix = "floatBitsToInt";
|
|
|
|
svec4 = "ivec4";
|
|
|
|
stprefix = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instno == 0) {
|
|
|
|
sret = add_str_to_glsl_main(ctx, "void main(void)\n{\n");
|
|
|
|
if (!sret)
|
|
|
|
return FALSE;
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
ret = emit_color_select(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
|
|
|
|
const struct tgsi_full_dst_register *dst = &inst->Dst[i];
|
|
|
|
if (dst->Register.WriteMask != TGSI_WRITEMASK_XYZW) {
|
|
|
|
int wm_idx = 0;
|
|
|
|
writemask[wm_idx++] = '.';
|
|
|
|
if (dst->Register.WriteMask & 0x1)
|
|
|
|
writemask[wm_idx++] = 'x';
|
|
|
|
if (dst->Register.WriteMask & 0x2)
|
|
|
|
writemask[wm_idx++] = 'y';
|
|
|
|
if (dst->Register.WriteMask & 0x4)
|
|
|
|
writemask[wm_idx++] = 'z';
|
|
|
|
if (dst->Register.WriteMask & 0x8)
|
|
|
|
writemask[wm_idx++] = 'w';
|
|
|
|
if (wm_idx == 2) {
|
|
|
|
snprintf(dstconv, 6, "float");
|
|
|
|
snprintf(udstconv, 6, "uint");
|
|
|
|
} else {
|
|
|
|
snprintf(dstconv, 6, "vec%d", wm_idx-1);
|
|
|
|
snprintf(udstconv, 6, "uvec%d", wm_idx-1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf(dstconv, 6, "vec4");
|
|
|
|
snprintf(udstconv, 6, "uvec4");
|
|
|
|
}
|
|
|
|
if (dst->Register.File == TGSI_FILE_OUTPUT) {
|
|
|
|
for (j = 0; j < ctx->num_outputs; j++) {
|
|
|
|
if (ctx->outputs[j].first == dst->Register.Index) {
|
|
|
|
if (ctx->glsl_ver_required >= 140 && ctx->outputs[j].name == TGSI_SEMANTIC_CLIPVERTEX) {
|
|
|
|
snprintf(dsts[i], 255, "clipv_tmp");
|
|
|
|
} else if (ctx->outputs[j].name == TGSI_SEMANTIC_CLIPDIST) {
|
|
|
|
snprintf(dsts[i], 255, "clip_dist_temp[%d]", ctx->outputs[j].sid);
|
|
|
|
} else {
|
|
|
|
snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
|
|
|
|
if (ctx->outputs[j].is_int) {
|
|
|
|
if (!strcmp(dtypeprefix, ""))
|
|
|
|
dtypeprefix = "floatBitsToInt";
|
|
|
|
snprintf(dstconv, 6, "int");
|
|
|
|
}
|
|
|
|
if (ctx->outputs[j].name == TGSI_SEMANTIC_PSIZE) {
|
|
|
|
snprintf(dstconv, 6, "float");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dst->Register.File == TGSI_FILE_TEMPORARY) {
|
|
|
|
if (dst->Register.Indirect) {
|
|
|
|
snprintf(dsts[i], 255, "temps[addr0 + %d]%s", dst->Register.Index, writemask);
|
|
|
|
} else
|
|
|
|
snprintf(dsts[i], 255, "temps[%d]%s", dst->Register.Index, writemask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
|
|
|
|
const struct tgsi_full_src_register *src = &inst->Src[i];
|
|
|
|
char swizzle[8] = {0};
|
|
|
|
char prefix[6] = {0};
|
|
|
|
char arrayname[8] = {0};
|
|
|
|
int swz_idx = 0, pre_idx = 0;
|
|
|
|
boolean isabsolute = src->Register.Absolute;
|
|
|
|
|
|
|
|
override_no_wm[i] = false;
|
|
|
|
if (isabsolute)
|
|
|
|
swizzle[swz_idx++] = ')';
|
|
|
|
|
|
|
|
if (src->Register.Negate)
|
|
|
|
prefix[pre_idx++] = '-';
|
|
|
|
if (isabsolute)
|
|
|
|
strcpy(&prefix[pre_idx++], "abs(");
|
|
|
|
|
|
|
|
if (src->Register.Dimension)
|
|
|
|
sprintf(arrayname, "[%d]", src->Dimension.Index);
|
|
|
|
|
|
|
|
if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
|
|
|
|
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
|
|
|
|
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
|
|
|
|
src->Register.SwizzleW != TGSI_SWIZZLE_W) {
|
|
|
|
swizzle[swz_idx++] = '.';
|
|
|
|
swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleX);
|
|
|
|
swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleY);
|
|
|
|
swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleZ);
|
|
|
|
swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleW);
|
|
|
|
}
|
|
|
|
if (src->Register.File == TGSI_FILE_INPUT) {
|
|
|
|
for (j = 0; j < ctx->num_inputs; j++)
|
|
|
|
if (ctx->inputs[j].first == src->Register.Index) {
|
|
|
|
if (ctx->key->color_two_side && ctx->inputs[j].name == TGSI_SEMANTIC_COLOR)
|
|
|
|
snprintf(srcs[i], 255, "%s(%s%s%d%s%s)", stypeprefix, prefix, "realcolor", ctx->inputs[j].sid, arrayname, swizzle);
|
|
|
|
else if (ctx->inputs[j].glsl_gl_in) {
|
|
|
|
/* GS input clipdist requires a conversion */
|
|
|
|
if (ctx->inputs[j].name == TGSI_SEMANTIC_CLIPDIST) {
|
|
|
|
int idx;
|
|
|
|
idx = ctx->inputs[j].sid * 4;
|
|
|
|
idx += src->Register.SwizzleX;
|
|
|
|
snprintf(srcs[i], 255, "%s(vec4(%sgl_in%s.%s[%d]))", stypeprefix, prefix, arrayname, ctx->inputs[j].glsl_name, idx);
|
|
|
|
} else {
|
|
|
|
snprintf(srcs[i], 255, "%s(vec4(%sgl_in%s.%s)%s)", stypeprefix, prefix, arrayname, ctx->inputs[j].glsl_name, swizzle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ctx->inputs[j].name == TGSI_SEMANTIC_PRIMID)
|
|
|
|
snprintf(srcs[i], 255, "%s(vec4(intBitsToFloat(%s)))", stypeprefix, ctx->inputs[j].glsl_name);
|
|
|
|
else if (ctx->inputs[j].name == TGSI_SEMANTIC_FACE)
|
|
|
|
snprintf(srcs[i], 255, "%s(%s ? 1.0 : -1.0)", stypeprefix, ctx->inputs[j].glsl_name);
|
|
|
|
else
|
|
|
|
snprintf(srcs[i], 255, "%s(%s%s%s%s)", stypeprefix, prefix, ctx->inputs[j].glsl_name, arrayname, swizzle);
|
|
|
|
override_no_wm[i] = ctx->inputs[j].override_no_wm;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src->Register.File == TGSI_FILE_TEMPORARY) {
|
|
|
|
if (src->Register.Indirect) {
|
|
|
|
snprintf(srcs[i], 255, "%s%c%stemps[addr0 + %d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, src->Register.Index, swizzle, stprefix ? ')' : ' ');
|
|
|
|
} else
|
|
|
|
snprintf(srcs[i], 255, "%s%c%stemps[%d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, src->Register.Index, swizzle, stprefix ? ')' : ' ');
|
|
|
|
} else if (src->Register.File == TGSI_FILE_CONSTANT) {
|
|
|
|
const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
int dim = 0;
|
|
|
|
if (src->Register.Dimension) {
|
|
|
|
dim = src->Dimension.Index;
|
|
|
|
if (src->Register.Indirect) {
|
|
|
|
snprintf(srcs[i], 255, "%s(%s%subo%dcontents[addr0 + %d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
|
|
|
|
} else
|
|
|
|
snprintf(srcs[i], 255, "%s(%s%subo%dcontents[%d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
|
|
|
|
} else {
|
|
|
|
const char *csp;
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
if (stype == TGSI_TYPE_FLOAT || stype == TGSI_TYPE_UNTYPED)
|
|
|
|
csp = "uintBitsToFloat";
|
|
|
|
else if (stype == TGSI_TYPE_SIGNED)
|
|
|
|
csp = "ivec4";
|
|
|
|
else
|
|
|
|
csp = "";
|
|
|
|
|
|
|
|
if (src->Register.Indirect) {
|
|
|
|
snprintf(srcs[i], 255, "%s%s(%sconst%d[addr0 + %d]%s)", prefix, csp, cname, dim, src->Register.Index, swizzle);
|
|
|
|
} else
|
|
|
|
snprintf(srcs[i], 255, "%s%s(%sconst%d[%d]%s)", prefix, csp, cname, dim, src->Register.Index, swizzle);
|
|
|
|
}
|
|
|
|
} else if (src->Register.File == TGSI_FILE_SAMPLER) {
|
|
|
|
const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
snprintf(srcs[i], 255, "%ssamp%d%s", cname, src->Register.Index, swizzle);
|
|
|
|
sreg_index = src->Register.Index;
|
|
|
|
} else if (src->Register.File == TGSI_FILE_IMMEDIATE) {
|
|
|
|
struct immed *imd = &ctx->imm[(src->Register.Index)];
|
|
|
|
int idx = src->Register.SwizzleX;
|
|
|
|
char temp[48];
|
|
|
|
const char *vtype = "vec4";
|
|
|
|
const char *imm_stypeprefix = stypeprefix;
|
|
|
|
|
|
|
|
if (imd->type == TGSI_IMM_UINT32 || imd->type == TGSI_IMM_INT32) {
|
|
|
|
if (imd->type == TGSI_IMM_UINT32)
|
|
|
|
vtype = "uvec4";
|
|
|
|
else
|
|
|
|
vtype = "ivec4";
|
|
|
|
|
|
|
|
if (stype == TGSI_TYPE_UNSIGNED && imd->type == TGSI_IMM_INT32)
|
|
|
|
imm_stypeprefix = "uvec4";
|
|
|
|
else if (stype == TGSI_TYPE_SIGNED && imd->type == TGSI_IMM_UINT32)
|
|
|
|
imm_stypeprefix = "ivec4";
|
|
|
|
else if (stype == TGSI_TYPE_FLOAT || stype == TGSI_TYPE_UNTYPED) {
|
|
|
|
if (imd->type == TGSI_IMM_INT32)
|
|
|
|
imm_stypeprefix = "intBitsToFloat";
|
|
|
|
else
|
|
|
|
imm_stypeprefix = "uintBitsToFloat";
|
|
|
|
} else if (stype == TGSI_TYPE_UNSIGNED || stype == TGSI_TYPE_SIGNED)
|
|
|
|
imm_stypeprefix = "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build up a vec4 of immediates */
|
|
|
|
snprintf(srcs[i], 255, "%s(%s%s(", imm_stypeprefix, prefix, vtype);
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
if (j == 0)
|
|
|
|
idx = src->Register.SwizzleX;
|
|
|
|
else if (j == 1)
|
|
|
|
idx = src->Register.SwizzleY;
|
|
|
|
else if (j == 2)
|
|
|
|
idx = src->Register.SwizzleZ;
|
|
|
|
else if (j == 3)
|
|
|
|
idx = src->Register.SwizzleW;
|
|
|
|
switch (imd->type) {
|
|
|
|
case TGSI_IMM_FLOAT32:
|
|
|
|
if (isinf(imd->val[idx].f) || isnan(imd->val[idx].f)) {
|
|
|
|
ctx->has_ints = TRUE;
|
|
|
|
snprintf(temp, 48, "uintBitsToFloat(%uU)", imd->val[idx].ui);
|
|
|
|
} else
|
|
|
|
snprintf(temp, 25, "%.8g", imd->val[idx].f);
|
|
|
|
break;
|
|
|
|
case TGSI_IMM_UINT32:
|
|
|
|
snprintf(temp, 25, "%uU", imd->val[idx].ui);
|
|
|
|
break;
|
|
|
|
case TGSI_IMM_INT32:
|
|
|
|
snprintf(temp, 25, "%d", imd->val[idx].i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
strncat(srcs[i], temp, 255);
|
|
|
|
if (j < 3)
|
|
|
|
strcat(srcs[i], ",");
|
|
|
|
else {
|
|
|
|
snprintf(temp, 4, "))%c", isabsolute ? ')' : 0);
|
|
|
|
strncat(srcs[i], temp, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (src->Register.File == TGSI_FILE_SYSTEM_VALUE) {
|
|
|
|
for (j = 0; j < ctx->num_system_values; j++)
|
|
|
|
if (ctx->system_values[j].first == src->Register.Index) {
|
|
|
|
if (ctx->system_values[j].name == TGSI_SEMANTIC_VERTEXID)
|
|
|
|
snprintf(srcs[i], 255, "%s(vec4(intBitsToFloat(%s)))", stypeprefix, ctx->system_values[j].glsl_name);
|
|
|
|
else
|
|
|
|
snprintf(srcs[i], 255, "%s%s", prefix, ctx->system_values[j].glsl_name);
|
|
|
|
override_no_wm[i] = ctx->system_values[j].override_no_wm;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (inst->Instruction.Opcode) {
|
|
|
|
case TGSI_OPCODE_SQRT:
|
|
|
|
snprintf(buf, 255, "%s = sqrt(vec4(%s))%s;\n", dsts[0], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_LRP:
|
|
|
|
snprintf(buf, 255, "%s = mix(vec4(%s), vec4(%s), vec4(%s))%s;\n", dsts[0], srcs[2], srcs[1], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DP2:
|
|
|
|
snprintf(buf, 255, "%s = %s(dot(vec2(%s), vec2(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DP3:
|
|
|
|
snprintf(buf, 255, "%s = %s(dot(vec3(%s), vec3(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DP4:
|
|
|
|
snprintf(buf, 255, "%s = %s(dot(vec4(%s), vec4(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DPH:
|
|
|
|
snprintf(buf, 255, "%s = %s(dot(vec4(vec3(%s), 1.0), vec4(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MAX:
|
|
|
|
case TGSI_OPCODE_IMAX:
|
|
|
|
case TGSI_OPCODE_UMAX:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(max(%s, %s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MIN:
|
|
|
|
case TGSI_OPCODE_IMIN:
|
|
|
|
case TGSI_OPCODE_UMIN:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(min(%s, %s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ABS:
|
|
|
|
case TGSI_OPCODE_IABS:
|
|
|
|
emit_op1("abs");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_KILL_IF:
|
|
|
|
snprintf(buf, 255, "if (any(lessThan(%s, vec4(0.0))))\ndiscard;\n", srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_IF:
|
|
|
|
case TGSI_OPCODE_UIF:
|
|
|
|
snprintf(buf, 255, "if (any(bvec4(%s))) {\n", srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
ctx->indent_level++;
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ELSE:
|
|
|
|
snprintf(buf, 255, "} else {\n");
|
|
|
|
ctx->indent_level--;
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
ctx->indent_level++;
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ENDIF:
|
|
|
|
snprintf(buf, 255, "}\n");
|
|
|
|
ctx->indent_level--;
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_KILL:
|
|
|
|
snprintf(buf, 255, "discard;\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DST:
|
|
|
|
snprintf(buf, 512, "%s = vec4(1.0, %s.y * %s.y, %s.z, %s.w);\n", dsts[0],
|
|
|
|
srcs[0], srcs[1], srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_LIT:
|
|
|
|
snprintf(buf, 512, "%s = %s(vec4(1.0, max(%s.x, 0.0), step(0.0, %s.x) * pow(max(0.0, %s.y), clamp(%s.w, -128.0, 128.0)), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_EX2:
|
|
|
|
emit_op1("exp2");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_LG2:
|
|
|
|
emit_op1("log2");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_EXP:
|
|
|
|
snprintf(buf, 512, "%s = %s(vec4(pow(2.0, floor(%s.x)), %s.x - floor(%s.x), exp2(%s.x), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_LOG:
|
|
|
|
snprintf(buf, 512, "%s = %s(vec4(floor(log2(%s.x)), %s.x / pow(2.0, floor(log2(%s.x))), log2(%s.x), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_COS:
|
|
|
|
emit_op1("cos");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SIN:
|
|
|
|
emit_op1("sin");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SCS:
|
|
|
|
snprintf(buf, 255, "%s = %s(vec4(cos(%s.x), sin(%s.x), 0, 1)%s);\n", dsts[0], dstconv,
|
|
|
|
srcs[0], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DDX:
|
|
|
|
emit_op1("dFdx");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DDY:
|
|
|
|
emit_op1("dFdy");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_RCP:
|
|
|
|
snprintf(buf, 255, "%s = %s(1.0/(%s));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_FLR:
|
|
|
|
emit_op1("floor");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ROUND:
|
|
|
|
emit_op1("round");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ISSG:
|
|
|
|
emit_op1("sign");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_CEIL:
|
|
|
|
emit_op1("ceil");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_FRC:
|
|
|
|
emit_op1("fract");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_TRUNC:
|
|
|
|
emit_op1("trunc");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SSG:
|
|
|
|
emit_op1("sign");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_RSQ:
|
|
|
|
snprintf(buf, 255, "%s = %s(inversesqrt(%s.x));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MOV:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(%s%s));\n", dsts[0], dstconv, dtypeprefix, srcs[0], override_no_wm[0] ? "" : writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ADD:
|
|
|
|
emit_arit_op2("+");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UADD:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(ivec4((uvec4(%s) + uvec4(%s))))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SUB:
|
|
|
|
emit_arit_op2("-");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MUL:
|
|
|
|
emit_arit_op2("*");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_DIV:
|
|
|
|
emit_arit_op2("/");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UMUL:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s((uvec4(%s) * uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UMOD:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s((uvec4(%s) %% uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_IDIV:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s((ivec4(%s) / ivec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UDIV:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s((uvec4(%s) / uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ISHR:
|
|
|
|
case TGSI_OPCODE_USHR:
|
|
|
|
emit_arit_op2(">>");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SHL:
|
|
|
|
emit_arit_op2("<<");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MAD:
|
|
|
|
snprintf(buf, 255, "%s = %s((%s * %s + %s)%s);\n", dsts[0], dstconv, srcs[0], srcs[1], srcs[2], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UMAD:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s((%s * %s + %s)%s));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], srcs[2], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_OR:
|
|
|
|
emit_arit_op2("|");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_AND:
|
|
|
|
emit_arit_op2("&");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_XOR:
|
|
|
|
emit_arit_op2("^");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_MOD:
|
|
|
|
emit_arit_op2("%");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_TEX:
|
|
|
|
case TGSI_OPCODE_TEX2:
|
|
|
|
case TGSI_OPCODE_TXB:
|
|
|
|
case TGSI_OPCODE_TXL:
|
|
|
|
case TGSI_OPCODE_TXB2:
|
|
|
|
case TGSI_OPCODE_TXL2:
|
|
|
|
case TGSI_OPCODE_TXD:
|
|
|
|
case TGSI_OPCODE_TXF:
|
|
|
|
case TGSI_OPCODE_TG4:
|
|
|
|
case TGSI_OPCODE_TXP:
|
|
|
|
case TGSI_OPCODE_TXQ:
|
|
|
|
case TGSI_OPCODE_LODQ:
|
|
|
|
ret = translate_tex(ctx, inst, sreg_index, srcs, dsts, writemask, dstconv, dtypeprefix);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_I2F:
|
|
|
|
snprintf(buf, 255, "%s = %s(ivec4(%s));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_U2F:
|
|
|
|
snprintf(buf, 255, "%s = %s(uvec4(%s));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_F2I:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(ivec4(%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_F2U:
|
|
|
|
snprintf(buf, 255, "%s = %s(%s(uvec4(%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_NOT:
|
|
|
|
snprintf(buf, 255, "%s = %s(uintBitsToFloat(~(uvec4(%s))));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_INEG:
|
|
|
|
snprintf(buf, 255, "%s = %s(intBitsToFloat(-(ivec4(%s))));\n", dsts[0], dstconv, srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SEQ:
|
|
|
|
emit_compare("equal");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_USEQ:
|
|
|
|
case TGSI_OPCODE_FSEQ:
|
|
|
|
emit_ucompare("equal");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SLT:
|
|
|
|
emit_compare("lessThan");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ISLT:
|
|
|
|
case TGSI_OPCODE_USLT:
|
|
|
|
case TGSI_OPCODE_FSLT:
|
|
|
|
emit_ucompare("lessThan");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SNE:
|
|
|
|
emit_compare("notEqual");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_USNE:
|
|
|
|
case TGSI_OPCODE_FSNE:
|
|
|
|
emit_ucompare("notEqual");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_SGE:
|
|
|
|
emit_compare("greaterThanEqual");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ISGE:
|
|
|
|
case TGSI_OPCODE_USGE:
|
|
|
|
case TGSI_OPCODE_FSGE:
|
|
|
|
emit_ucompare("greaterThanEqual");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_POW:
|
|
|
|
snprintf(buf, 255, "%s = %s(pow(%s, %s));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_CMP:
|
|
|
|
snprintf(buf, 255, "%s = mix(%s, %s, greaterThanEqual(%s, vec4(0.0)))%s;\n", dsts[0], srcs[1], srcs[2], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UCMP:
|
|
|
|
snprintf(buf, 255, "%s = mix(%s, %s, notEqual(floatBitsToUint(%s), uvec4(0.0)))%s;\n", dsts[0], srcs[2], srcs[1], srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_END:
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
|
|
|
|
if (ctx->so && !ctx->key->gs_present) {
|
|
|
|
ret = emit_so_movs(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ret = emit_prescale(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ret = emit_clip_dist_movs(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
|
|
|
|
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (ctx->key->pstipple_tex) {
|
|
|
|
ret = emit_pstipple_pass(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (ctx->key->add_alpha_test) {
|
|
|
|
ret = emit_alpha_test(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (ctx->write_all_cbufs) {
|
|
|
|
ret = emit_cbuf_writes(ctx);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sret = add_str_to_glsl_main(ctx, "}\n");
|
|
|
|
if (!sret)
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_RET:
|
|
|
|
EMIT_BUF_WITH_RET(ctx, "return;\n");
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ARL:
|
|
|
|
snprintf(buf, 255, "addr0 = int(floor(%s)%s);\n", srcs[0], writemask);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_UARL:
|
|
|
|
snprintf(buf, 255, "addr0 = int(%s);\n", srcs[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_XPD:
|
|
|
|
snprintf(buf, 255, "%s = %s(cross(vec3(%s), vec3(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_BGNLOOP:
|
|
|
|
snprintf(buf, 255, "do {\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
ctx->indent_level++;
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ENDLOOP:
|
|
|
|
ctx->indent_level--;
|
|
|
|
snprintf(buf, 255, "} while(true);\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_BRK:
|
|
|
|
snprintf(buf, 255, "break;\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_EMIT:
|
|
|
|
if (ctx->so && ctx->key->gs_present)
|
|
|
|
emit_so_movs(ctx);
|
|
|
|
emit_clip_dist_movs(ctx);
|
|
|
|
snprintf(buf, 255, "EmitVertex();\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
case TGSI_OPCODE_ENDPRIM:
|
|
|
|
snprintf(buf, 255, "EndPrimitive();\n");
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr,"failed to convert opcode %d\n", inst->Instruction.Opcode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) {
|
|
|
|
snprintf(buf, 255, "%s = clamp(%s, 0.0, 1.0);\n", dsts[0], dsts[0]);
|
|
|
|
EMIT_BUF_WITH_RET(ctx, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
prolog(struct tgsi_iterate_context *iter)
|
|
|
|
{
|
|
|
|
struct dump_ctx *ctx = (struct dump_ctx *)iter;
|
|
|
|
|
|
|
|
if (ctx->prog_type == -1)
|
|
|
|
ctx->prog_type = iter->processor.Processor;
|
|
|
|
|
|
|
|
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX &&
|
|
|
|
ctx->key->gs_present)
|
|
|
|
ctx->glsl_ver_required = 150;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STRCAT_WITH_RET(mainstr, buf) do { \
|
|
|
|
(mainstr) = strcat_realloc((mainstr), (buf)); \
|
|
|
|
if ((mainstr) == NULL) return NULL; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
|
|
|
|
{
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY || ctx->glsl_ver_required == 150)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#version 150\n");
|
|
|
|
|
|
|
|
else if (ctx->glsl_ver_required == 140)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#version 140\n");
|
|
|
|
else
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#version 130\n");
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && vrend_shader_use_explicit)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_explicit_attrib_location : enable\n");
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT && fs_emit_layout(ctx))
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_fragment_coord_conventions : enable\n");
|
|
|
|
if (ctx->glsl_ver_required < 140 && ctx->uses_sampler_rect)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_rectangle : require\n");
|
|
|
|
if (ctx->uses_cube_array)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_cube_map_array : require\n");
|
|
|
|
if (ctx->has_ints)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_bit_encoding : require\n");
|
|
|
|
if (ctx->uses_sampler_ms)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_multisample : require\n");
|
|
|
|
if (ctx->has_instanceid)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_draw_instanced : require\n");
|
|
|
|
if (ctx->num_ubo)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_uniform_buffer_object : require\n");
|
|
|
|
if (ctx->uses_lodq)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_query_lod : require\n");
|
|
|
|
if (ctx->uses_txq_levels)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_query_levels : require\n");
|
|
|
|
if (ctx->uses_tg4)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_gather : require\n");
|
|
|
|
if (ctx->has_viewport_idx)
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_viewport_array : require\n");
|
|
|
|
return glsl_hdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *vrend_shader_samplertypeconv(int sampler_type, int *is_shad)
|
|
|
|
{
|
|
|
|
switch (sampler_type) {
|
|
|
|
case TGSI_TEXTURE_BUFFER: return "Buffer";
|
|
|
|
case TGSI_TEXTURE_1D: return "1D";
|
|
|
|
case TGSI_TEXTURE_2D: return "2D";
|
|
|
|
case TGSI_TEXTURE_3D: return "3D";
|
|
|
|
case TGSI_TEXTURE_CUBE: return "Cube";
|
|
|
|
case TGSI_TEXTURE_RECT: return "2DRect";
|
|
|
|
case TGSI_TEXTURE_SHADOW1D: *is_shad = 1; return "1DShadow";
|
|
|
|
case TGSI_TEXTURE_SHADOW2D: *is_shad = 1; return "2DShadow";
|
|
|
|
case TGSI_TEXTURE_SHADOWRECT: *is_shad = 1; return "2DRectShadow";
|
|
|
|
case TGSI_TEXTURE_1D_ARRAY: return "1DArray";
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY: return "2DArray";
|
|
|
|
case TGSI_TEXTURE_SHADOW1D_ARRAY: *is_shad = 1; return "1DArrayShadow";
|
|
|
|
case TGSI_TEXTURE_SHADOW2D_ARRAY: *is_shad = 1; return "2DArrayShadow";
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE: *is_shad = 1; return "CubeShadow";
|
|
|
|
case TGSI_TEXTURE_CUBE_ARRAY: return "CubeArray";
|
|
|
|
case TGSI_TEXTURE_SHADOWCUBE_ARRAY: *is_shad = 1; return "CubeArrayShadow";
|
|
|
|
case TGSI_TEXTURE_2D_MSAA: return "2DMS";
|
|
|
|
case TGSI_TEXTURE_2D_ARRAY_MSAA: return "2DMSArray";
|
|
|
|
default: return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *get_interp_string(int interpolate, boolean flatshade)
|
|
|
|
{
|
|
|
|
switch (interpolate) {
|
|
|
|
case TGSI_INTERPOLATE_LINEAR:
|
|
|
|
return "noperspective ";
|
|
|
|
case TGSI_INTERPOLATE_PERSPECTIVE:
|
|
|
|
return "smooth ";
|
|
|
|
case TGSI_INTERPOLATE_CONSTANT:
|
|
|
|
return "flat ";
|
|
|
|
case TGSI_INTERPOLATE_COLOR:
|
|
|
|
if (flatshade)
|
|
|
|
return "flat ";
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char buf[255];
|
|
|
|
char postfix[8];
|
|
|
|
const char *prefix = "";
|
|
|
|
|
|
|
|
ctx->num_interps = 0;
|
|
|
|
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT) {
|
|
|
|
if (fs_emit_layout(ctx)) {
|
|
|
|
boolean upper_left = !(ctx->fs_coord_origin ^ ctx->key->invert_fs_origin);
|
|
|
|
char comma = (upper_left && ctx->fs_pixel_center) ? ',' : ' ';
|
|
|
|
|
|
|
|
snprintf(buf, 255, "layout(%s%c%s) in vec4 gl_FragCoord;\n",
|
|
|
|
upper_left ? "origin_upper_left" : "",
|
|
|
|
comma,
|
|
|
|
ctx->fs_pixel_center ? "pixel_center_integer" : "");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
snprintf(buf, 255, "layout(%s) in;\n", prim_to_name(ctx->gs_in_prim));
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
snprintf(buf, 255, "layout(%s, max_vertices = %d) out;\n", prim_to_name(ctx->gs_out_prim), ctx->gs_max_out_verts);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
for (i = 0; i < ctx->num_inputs; i++) {
|
|
|
|
if (!ctx->inputs[i].glsl_predefined_no_emit) {
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && vrend_shader_use_explicit) {
|
|
|
|
snprintf(buf, 255, "layout(location=%d) ", ctx->inputs[i].first);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT &&
|
|
|
|
(ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC ||
|
|
|
|
ctx->inputs[i].name == TGSI_SEMANTIC_COLOR)) {
|
|
|
|
prefix = get_interp_string(ctx->inputs[i].interpolate, ctx->key->flatshade);
|
|
|
|
if (!prefix)
|
|
|
|
prefix = "";
|
|
|
|
ctx->num_interps++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
snprintf(postfix, 8, "[%d]", gs_input_prim_to_size(ctx->gs_in_prim));
|
|
|
|
} else
|
|
|
|
postfix[0] = 0;
|
|
|
|
snprintf(buf, 255, "%sin vec4 %s%s;\n", prefix, ctx->inputs[i].glsl_name, postfix);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ctx->write_all_cbufs) {
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
snprintf(buf, 255, "out vec4 fsout_c%d;\n", i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < ctx->num_outputs; i++) {
|
|
|
|
if (!ctx->outputs[i].glsl_predefined_no_emit) {
|
|
|
|
if ((ctx->prog_type == TGSI_PROCESSOR_VERTEX || ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) && (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC || ctx->outputs[i].name == TGSI_SEMANTIC_COLOR || ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)) {
|
|
|
|
ctx->num_interps++;
|
|
|
|
prefix = INTERP_PREFIX;
|
|
|
|
} else
|
|
|
|
prefix = "";
|
|
|
|
/* ugly leave spaces to patch interp in later */
|
|
|
|
snprintf(buf, 255, "%sout vec4 %s;\n", prefix, ctx->outputs[i].glsl_name);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_VERTEX) {
|
|
|
|
snprintf(buf, 255, "uniform vec4 winsys_adjust;\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
|
|
|
|
if (ctx->has_clipvertex) {
|
|
|
|
snprintf(buf, 255, "%svec4 clipv_tmp;\n", ctx->has_clipvertex_so ? "out " : "");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->num_clip_dist || ctx->key->clip_plane_enable) {
|
|
|
|
|
|
|
|
if (ctx->key->clip_plane_enable) {
|
|
|
|
snprintf(buf, 255, "uniform vec4 clipp[8];\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->key->gs_present) {
|
|
|
|
snprintf(buf, 255, "out gl_PerVertex {\n vec4 gl_Position;\n float gl_PointSize;\n float gl_ClipDistance[%d];\n};\n", ctx->num_clip_dist ? ctx->num_clip_dist : 8);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
} else {
|
|
|
|
snprintf(buf, 255, "out float gl_ClipDistance[%d];\n", ctx->num_clip_dist ? ctx->num_clip_dist : 8);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
snprintf(buf, 255, "vec4 clip_dist_temp[2];\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) {
|
|
|
|
if (ctx->num_in_clip_dist || ctx->key->clip_plane_enable) {
|
|
|
|
snprintf(buf, 255, "in gl_PerVertex {\n vec4 gl_Position;\n float gl_PointSize; \n float gl_ClipDistance[%d];\n} gl_in[];\n", ctx->num_in_clip_dist ? ctx->num_in_clip_dist : 8);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->num_clip_dist) {
|
|
|
|
snprintf(buf, 255, "out float gl_ClipDistance[%d];\n", ctx->num_clip_dist);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
snprintf(buf, 255, "vec4 clip_dist_temp[2];\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->so) {
|
|
|
|
char outtype[6] = {0};
|
|
|
|
for (i = 0; i < ctx->so->num_outputs; i++) {
|
|
|
|
if (!ctx->write_so_outputs[i])
|
|
|
|
continue;
|
|
|
|
if (ctx->so->output[i].num_components == 1)
|
|
|
|
snprintf(outtype, 6, "float");
|
|
|
|
else
|
|
|
|
snprintf(outtype, 6, "vec%d", ctx->so->output[i].num_components);
|
|
|
|
snprintf(buf, 255, "out %s tfout%d;\n", outtype, i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ctx->num_temps) {
|
|
|
|
snprintf(buf, 255, "vec4 temps[%d];\n", ctx->num_temps);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->num_address; i++) {
|
|
|
|
snprintf(buf, 255, "int addr%d;\n", i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->num_consts) {
|
|
|
|
const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
snprintf(buf, 255, "uniform uvec4 %sconst0[%d];\n", cname, ctx->num_consts);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->key->color_two_side) {
|
|
|
|
if (ctx->color_in_mask & 1) {
|
|
|
|
snprintf(buf, 255, "vec4 realcolor0;\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
if (ctx->color_in_mask & 2) {
|
|
|
|
snprintf(buf, 255, "vec4 realcolor1;\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ctx->num_ubo) {
|
|
|
|
for (i = 0; i < ctx->num_ubo; i++) {
|
|
|
|
const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
snprintf(buf, 255, "uniform %subo%d { vec4 %subo%dcontents[%d]; };\n", cname, ctx->ubo_idx[i], cname, ctx->ubo_idx[i], ctx->ubo_sizes[i]);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
int is_shad = 0;
|
|
|
|
const char *stc;
|
|
|
|
|
|
|
|
if ((ctx->samplers_used & (1 << i)) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
stc = vrend_shader_samplertypeconv(ctx->samplers[i].tgsi_sampler_type, &is_shad);
|
|
|
|
|
|
|
|
if (stc) {
|
|
|
|
const char *sname;
|
|
|
|
|
|
|
|
sname = tgsi_proc_to_prefix(ctx->prog_type);
|
|
|
|
snprintf(buf, 255, "uniform sampler%s %ssamp%d;\n", stc, sname, i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
if (is_shad) {
|
|
|
|
snprintf(buf, 255, "uniform vec4 %sshadmask%d;\n", sname, i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
snprintf(buf, 255, "uniform vec4 %sshadadd%d;\n", sname, i);
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
ctx->shadow_samp_mask |= (1 << i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT &&
|
|
|
|
ctx->key->pstipple_tex == true) {
|
|
|
|
snprintf(buf, 255, "uniform sampler2D pstipple_sampler;\nfloat stip_temp;\n");
|
|
|
|
STRCAT_WITH_RET(glsl_hdr, buf);
|
|
|
|
}
|
|
|
|
return glsl_hdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean fill_fragment_interpolants(struct dump_ctx *ctx, struct vrend_shader_info *sinfo)
|
|
|
|
{
|
|
|
|
int i, index = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->num_inputs; i++) {
|
|
|
|
if (ctx->inputs[i].glsl_predefined_no_emit)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ctx->inputs[i].name != TGSI_SEMANTIC_GENERIC &&
|
|
|
|
ctx->inputs[i].name != TGSI_SEMANTIC_COLOR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (index >= ctx->num_interps) {
|
|
|
|
fprintf(stderr, "mismatch in number of interps %d %d\n", index, ctx->num_interps);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
sinfo->interpinfo[index].semantic_name = ctx->inputs[i].name;
|
|
|
|
sinfo->interpinfo[index].semantic_index = ctx->inputs[i].sid;
|
|
|
|
sinfo->interpinfo[index].interpolate = ctx->inputs[i].interpolate;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean fill_interpolants(struct dump_ctx *ctx, struct vrend_shader_info *sinfo)
|
|
|
|
{
|
|
|
|
boolean ret;
|
|
|
|
|
|
|
|
if (!ctx->num_interps)
|
|
|
|
return TRUE;
|
|
|
|
if (ctx->prog_type == TGSI_PROCESSOR_VERTEX || ctx->prog_type == TGSI_PROCESSOR_GEOMETRY)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
sinfo->interpinfo = calloc(ctx->num_interps, sizeof(struct vrend_interp_info));
|
|
|
|
if (!sinfo->interpinfo)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ret = fill_fragment_interpolants(ctx, sinfo);
|
|
|
|
if (ret == FALSE)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
out_fail:
|
|
|
|
free(sinfo->interpinfo);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
|
|
|
|
const struct tgsi_token *tokens,
|
|
|
|
struct vrend_shader_key *key,
|
|
|
|
struct vrend_shader_info *sinfo)
|
|
|
|
{
|
|
|
|
struct dump_ctx ctx;
|
|
|
|
char *glsl_final = NULL;
|
|
|
|
boolean bret;
|
|
|
|
char *glsl_hdr = NULL;
|
|
|
|
|
|
|
|
memset(&ctx, 0, sizeof(struct dump_ctx));
|
|
|
|
ctx.iter.prolog = prolog;
|
|
|
|
ctx.iter.iterate_instruction = iter_instruction;
|
|
|
|
ctx.iter.iterate_declaration = iter_declaration;
|
|
|
|
ctx.iter.iterate_immediate = iter_immediate;
|
|
|
|
ctx.iter.iterate_property = iter_property;
|
|
|
|
ctx.iter.epilog = NULL;
|
|
|
|
ctx.key = key;
|
|
|
|
ctx.cfg = cfg;
|
|
|
|
ctx.prog_type = -1;
|
|
|
|
|
|
|
|
/* if we are in core profile mode we should use GLSL 1.40 */
|
|
|
|
if (cfg->use_core_profile && cfg->glsl_version >= 140)
|
|
|
|
ctx.glsl_ver_required = 140;
|
|
|
|
|
|
|
|
if (sinfo->so_info.num_outputs) {
|
|
|
|
ctx.so = &sinfo->so_info;
|
|
|
|
ctx.so_names = calloc(sinfo->so_info.num_outputs, sizeof(char *));
|
|
|
|
if (!ctx.so_names)
|
|
|
|
goto fail;
|
|
|
|
} else
|
|
|
|
ctx.so_names = NULL;
|
|
|
|
|
|
|
|
ctx.glsl_main = malloc(4096);
|
|
|
|
if (!ctx.glsl_main)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
ctx.glsl_main[0] = '\0';
|
|
|
|
bret = tgsi_iterate_shader(tokens, &ctx.iter);
|
|
|
|
if (bret == FALSE)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
glsl_hdr = malloc(1024);
|
|
|
|
if (!glsl_hdr)
|
|
|
|
goto fail;
|
|
|
|
glsl_hdr[0] = '\0';
|
|
|
|
glsl_hdr = emit_header(&ctx, glsl_hdr);
|
|
|
|
if (!glsl_hdr)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
glsl_hdr = emit_ios(&ctx, glsl_hdr);
|
|
|
|
if (!glsl_hdr)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
glsl_final = malloc(strlen(glsl_hdr) + strlen(ctx.glsl_main) + 1);
|
|
|
|
if (!glsl_final)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
glsl_final[0] = '\0';
|
|
|
|
|
|
|
|
bret = fill_interpolants(&ctx, sinfo);
|
|
|
|
if (bret == FALSE)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
strcat(glsl_final, glsl_hdr);
|
|
|
|
strcat(glsl_final, ctx.glsl_main);
|
|
|
|
if (vrend_dump_shaders)
|
|
|
|
fprintf(stderr,"GLSL: %s\n", glsl_final);
|
|
|
|
free(ctx.glsl_main);
|
|
|
|
free(glsl_hdr);
|
|
|
|
sinfo->num_ucp = ctx.key->clip_plane_enable ? 8 : 0;
|
|
|
|
sinfo->samplers_used_mask = ctx.samplers_used;
|
|
|
|
sinfo->num_consts = ctx.num_consts;
|
|
|
|
sinfo->num_ubos = ctx.num_ubo;
|
|
|
|
sinfo->num_inputs = ctx.num_inputs;
|
|
|
|
sinfo->num_interps = ctx.num_interps;
|
|
|
|
sinfo->num_outputs = ctx.num_outputs;
|
|
|
|
sinfo->shadow_samp_mask = ctx.shadow_samp_mask;
|
|
|
|
sinfo->glsl_ver = ctx.glsl_ver_required;
|
|
|
|
sinfo->gs_out_prim = ctx.gs_out_prim;
|
|
|
|
sinfo->so_names = ctx.so_names;
|
|
|
|
return glsl_final;
|
|
|
|
fail:
|
|
|
|
free(ctx.glsl_main);
|
|
|
|
free(glsl_final);
|
|
|
|
free(glsl_hdr);
|
|
|
|
free(ctx.so_names);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void replace_interp(char *program,
|
|
|
|
const char *var_name,
|
|
|
|
const char *pstring)
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
int mylen = strlen(INTERP_PREFIX) + strlen("out vec4 ");
|
|
|
|
|
|
|
|
ptr = strstr(program, var_name);
|
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ptr -= mylen;
|
|
|
|
|
|
|
|
memcpy(ptr, pstring, strlen(pstring));
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean vrend_patch_vertex_shader_interpolants(char *program,
|
|
|
|
struct vrend_shader_info *vs_info,
|
|
|
|
struct vrend_shader_info *fs_info, bool is_gs, bool flatshade)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *pstring;
|
|
|
|
char glsl_name[64];
|
|
|
|
if (!vs_info || !fs_info)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (!fs_info->interpinfo)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
for (i = 0; i < fs_info->num_interps; i++) {
|
|
|
|
pstring = get_interp_string(fs_info->interpinfo[i].interpolate, flatshade);
|
|
|
|
if (!pstring)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (fs_info->interpinfo[i].semantic_name) {
|
|
|
|
case TGSI_SEMANTIC_COLOR:
|
|
|
|
/* color is a bit trickier */
|
|
|
|
if (fs_info->glsl_ver < 140) {
|
|
|
|
if (fs_info->interpinfo[i].semantic_index == 1) {
|
|
|
|
replace_interp(program, "gl_FrontSecondaryColor", pstring);
|
|
|
|
replace_interp(program, "gl_BackSecondaryColor", pstring);
|
|
|
|
} else {
|
|
|
|
replace_interp(program, "gl_FrontColor", pstring);
|
|
|
|
replace_interp(program, "gl_BackColor", pstring);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf(glsl_name, 64, "ex_c%d", fs_info->interpinfo[i].semantic_index);
|
|
|
|
replace_interp(program, glsl_name, pstring);
|
|
|
|
snprintf(glsl_name, 64, "ex_bc%d", fs_info->interpinfo[i].semantic_index);
|
|
|
|
replace_interp(program, glsl_name, pstring);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGSI_SEMANTIC_GENERIC:
|
|
|
|
snprintf(glsl_name, 64, "%s_g%d", is_gs ? "out" : "ex", fs_info->interpinfo[i].semantic_index);
|
|
|
|
replace_interp(program, glsl_name, pstring);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vrend_dump_shaders)
|
|
|
|
fprintf(stderr,"GLSL: post interp: %s\n", program);
|
|
|
|
return TRUE;
|
|
|
|
}
|