From 4472641b3d6f4800e2ce6980516dd90ac7449f7a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 20 Jul 2018 08:40:07 +1000 Subject: [PATCH] shader: add image support to shader parsing. (v3) This converts the image related opcodes, and tracks the used images. Images need some extensions for extra features: ES_3_1_compatability is needed for r32f image support shader_image_size for image size support v2: image: fix missing emit for atomic, use a shader req for images extension extend cas_str - we overflowed this v2.1: drop extra breaks, use decl last for range check (Tomeu) v3: add indirect support, drop pointless debug print (Gert) use 512 in load path. Reviewed-by: Gert Wollny --- src/vrend_renderer.c | 1 + src/vrend_shader.c | 435 +++++++++++++++++++++++++++++++++++++++++-- src/vrend_shader.h | 9 + 3 files changed, 427 insertions(+), 18 deletions(-) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 16013cc..0c53348 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -749,6 +749,7 @@ static void vrend_destroy_shader_selector(struct vrend_shader_selector *sel) free(sel->sinfo.so_names); free(sel->sinfo.interpinfo); free(sel->sinfo.sampler_arrays); + free(sel->sinfo.image_arrays); free(sel->tokens); free(sel); } diff --git a/src/vrend_shader.c b/src/vrend_shader.c index ca4e18e..298ce03 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -56,6 +56,9 @@ extern int vrend_dump_shaders; #define SHADER_REQ_GPU_SHADER5 (1 << 12) #define SHADER_REQ_DERIVATIVE_CONTROL (1 << 13) #define SHADER_REQ_FP64 (1 << 14) +#define SHADER_REQ_IMAGE_LOAD_STORE (1 << 15) +#define SHADER_REQ_ES31_COMPAT (1 << 16) +#define SHADER_REQ_IMAGE_SIZE (1 << 17) struct vrend_shader_io { unsigned name; @@ -86,6 +89,12 @@ struct vrend_shader_table { const char *string; }; +struct vrend_shader_image { + struct tgsi_declaration_image decl; + enum tgsi_return_type image_return; + bool vflag; +}; + #define MAX_IMMEDIATE 1024 struct immed { int type; @@ -143,6 +152,12 @@ struct dump_ctx { uint32_t ssbo_array_base; uint32_t ssbo_atomic_array_base; + struct vrend_shader_image images[32]; + uint32_t images_used_mask; + + struct vrend_image_array *image_arrays; + uint32_t num_image_arrays; + struct vrend_sampler_array *sampler_arrays; uint32_t num_sampler_arrays; int last_sampler_array_idx; @@ -210,6 +225,9 @@ static const struct vrend_shader_table shader_req_table[] = { { SHADER_REQ_GPU_SHADER5, "GL_ARB_gpu_shader5" }, { SHADER_REQ_DERIVATIVE_CONTROL, "GL_ARB_derivative_control" }, { SHADER_REQ_FP64, "GL_ARB_gpu_shader_fp64" }, + { SHADER_REQ_IMAGE_LOAD_STORE, "GL_ARB_shader_image_load_store" }, + { SHADER_REQ_ES31_COMPAT, "GL_ARB_ES3_1_compatibility" }, + { SHADER_REQ_IMAGE_SIZE, "GL_ARB_shader_image_size" }, }; enum vrend_type_qualifier { @@ -301,6 +319,8 @@ static inline const char *get_wm_string(unsigned wm) } } +const char *get_internalformat_string(int virgl_format, enum tgsi_return_type *stype); + static inline const char *tgsi_proc_to_prefix(int shader_type) { switch (shader_type) { @@ -488,6 +508,53 @@ static struct vrend_temp_range *find_temp_range(struct dump_ctx *ctx, int index) return NULL; } +static int add_images(struct dump_ctx *ctx, int first, int last, + struct tgsi_declaration_image *img_decl) +{ + int i; + + for (i = first; i <= last; i++) { + ctx->images[i].decl = *img_decl; + ctx->images[i].vflag = false; + ctx->images_used_mask |= (1 << i); + + if (ctx->images[i].decl.Resource == TGSI_TEXTURE_CUBE_ARRAY) + ctx->shader_req_bits |= SHADER_REQ_CUBE_ARRAY; + else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_2D_MSAA || + ctx->images[i].decl.Resource == TGSI_TEXTURE_2D_ARRAY_MSAA) + ctx->shader_req_bits |= SHADER_REQ_SAMPLER_MS; + else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_BUFFER) + ctx->uses_sampler_buf = true; + else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_RECT) + ctx->shader_req_bits |= SHADER_REQ_SAMPLER_RECT; + } + + if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) { + if (ctx->num_image_arrays) { + struct vrend_image_array *last_array = &ctx->image_arrays[ctx->num_image_arrays - 1]; + /* + * If this set of images is consecutive to the last array, + * and has compatible return and decls, then increase the array size. + */ + if ((last_array->first + last_array->array_size == first) && + !memcmp(&ctx->images[last_array->first].decl, &ctx->images[first].decl, sizeof(ctx->images[first].decl)) && + ctx->images[last_array->first].image_return == ctx->images[first].image_return) { + last_array->array_size += last - first + 1; + return 0; + } + } + + /* allocate a new image array for this range of images */ + ctx->num_image_arrays++; + ctx->image_arrays = realloc(ctx->image_arrays, sizeof(struct vrend_image_array) * ctx->num_image_arrays); + if (!ctx->image_arrays) + return -1; + ctx->image_arrays[ctx->num_image_arrays - 1].first = first; + ctx->image_arrays[ctx->num_image_arrays - 1].array_size = last - first + 1; + } + return 0; +} + static int add_sampler_array(struct dump_ctx *ctx, int first, int last, int sview_type, int sview_rtype) { int idx = ctx->num_sampler_arrays; @@ -546,6 +613,18 @@ static bool ctx_indirect_outputs(struct dump_ctx *ctx) return false; } +static int lookup_image_array(struct dump_ctx *ctx, int index) +{ + uint32_t i; + for (i = 0; i < ctx->num_image_arrays; i++) { + if (index >= ctx->image_arrays[i].first && + index <= ctx->image_arrays[i].first + ctx->image_arrays[i].array_size - 1) { + return ctx->image_arrays[i].first; + } + } + return -1; +} + static boolean iter_declaration(struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl ) @@ -1049,6 +1128,18 @@ iter_declaration(struct tgsi_iterate_context *iter, } } break; + case TGSI_FILE_IMAGE: { + int ret; + ctx->shader_req_bits |= SHADER_REQ_IMAGE_LOAD_STORE; + if (decl->Range.Last >= ARRAY_SIZE(ctx->images)) { + fprintf(stderr, "Image view exceeded, max is %lu\n", ARRAY_SIZE(ctx->images)); + return FALSE; + } + ret = add_images(ctx, decl->Range.First, decl->Range.Last, &decl->Image); + if (ret == -1) + return FALSE; + break; + } case TGSI_FILE_BUFFER: if (decl->Range.First >= 32) { fprintf(stderr, "Buffer view exceeded, max is 32\n"); @@ -2144,6 +2235,32 @@ create_swizzled_clipdist(struct dump_ctx *ctx, snprintf(result, 255, "%s(vec4(%s,%s,%s,%s))", stypeprefix, clipdistvec[0], clipdistvec[1], clipdistvec[2], clipdistvec[3]); } +static enum vrend_type_qualifier get_coord_prefix(int resource, bool *is_ms) +{ + switch(resource) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_BUFFER: + return INT; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_1D_ARRAY: + return IVEC2; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_CUBE_ARRAY: + return IVEC3; + case TGSI_TEXTURE_2D_MSAA: + *is_ms = true; + return IVEC2; + case TGSI_TEXTURE_2D_ARRAY_MSAA: + *is_ms = true; + return IVEC3; + default: + return TYPE_CONVERSION_NONE; + } +} + static int translate_store(struct dump_ctx *ctx, struct tgsi_full_instruction *inst, @@ -2153,7 +2270,29 @@ translate_store(struct dump_ctx *ctx, const struct tgsi_full_dst_register *dst = &inst->Dst[0]; char buf[512]; - if (dst->Register.File == TGSI_FILE_BUFFER) { + if (dst->Register.File == TGSI_FILE_IMAGE) { + bool is_ms = false; + enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx->images[dst->Register.Index].decl.Resource, &is_ms); + enum tgsi_return_type itype; + char ms_str[32] = {}; + enum vrend_type_qualifier stypeprefix = TYPE_CONVERSION_NONE; + get_internalformat_string(inst->Memory.Format, &itype); + if (is_ms) { + snprintf(ms_str, 32, "int(%s.w),", srcs[0]); + } + switch (itype) { + case TGSI_RETURN_TYPE_UINT: + stypeprefix = FLOAT_BITS_TO_UINT; + break; + case TGSI_RETURN_TYPE_SINT: + stypeprefix = FLOAT_BITS_TO_INT; + break; + default: + break; + } + snprintf(buf, 512, "imageStore(%s,%s(floatBitsToInt(%s)),%s%s(%s));\n", dsts[0], get_string(coord_prefix), srcs[0], ms_str, get_string(stypeprefix), srcs[1]); + EMIT_BUF_WITH_RET(ctx, buf); + } else if (dst->Register.File == TGSI_FILE_BUFFER) { const char *conversion = get_string(FLOAT_BITS_TO_UINT); if (inst->Dst[0].Register.WriteMask & 0x1) { snprintf(buf, 255, "%s[uint(floatBitsToUint(%s))>>2] = %s(%s).x;\n", dsts[0], srcs[0], conversion, srcs[1]); @@ -2178,13 +2317,38 @@ translate_store(struct dump_ctx *ctx, static int translate_load(struct dump_ctx *ctx, struct tgsi_full_instruction *inst, + struct source_info *sinfo, + struct dest_info *dinfo, char srcs[4][255], - char dsts[3][255]) + char dsts[3][255], + const char *writemask) { char buf[512]; const struct tgsi_full_src_register *src = &inst->Src[0]; - - if (src->Register.File == TGSI_FILE_BUFFER) { + if (src->Register.File == TGSI_FILE_IMAGE) { + bool is_ms = false; + enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx->images[sinfo->sreg_index].decl.Resource, &is_ms); + enum vrend_type_qualifier dtypeprefix = TYPE_CONVERSION_NONE; + enum tgsi_return_type itype; + get_internalformat_string(ctx->images[sinfo->sreg_index].decl.Format, &itype); + char ms_str[32] = {}; + const char *wm = dinfo->dst_override_no_wm[0] ? "" : writemask; + if (is_ms) { + snprintf(ms_str, 32, ", int(%s.w)", srcs[1]); + } + switch (itype) { + case TGSI_RETURN_TYPE_UINT: + dtypeprefix = UINT_BITS_TO_FLOAT; + break; + case TGSI_RETURN_TYPE_SINT: + dtypeprefix = INT_BITS_TO_FLOAT; + break; + default: + break; + } + snprintf(buf, 512, "%s = %s(imageLoad(%s, %s(floatBitsToInt(%s))%s)%s);\n", dsts[0], get_string(dtypeprefix), srcs[0], get_string(coord_prefix), srcs[1], ms_str, wm); + EMIT_BUF_WITH_RET(ctx, buf); + } else if (src->Register.File == TGSI_FILE_BUFFER) { char mydst[255], atomic_op[9], atomic_src[10]; strcpy(mydst, dsts[0]); char *wmp = strchr(mydst, '.'); @@ -2270,7 +2434,11 @@ translate_resq(struct dump_ctx *ctx, struct tgsi_full_instruction *inst, char buf[512]; const struct tgsi_full_src_register *src = &inst->Src[0]; - if (src->Register.File == TGSI_FILE_BUFFER) { + if (src->Register.File == TGSI_FILE_IMAGE) { + ctx->shader_req_bits |= SHADER_REQ_IMAGE_SIZE; + snprintf(buf, 255, "%s = %s(imageSize(%s));\n", dsts[0], get_string(INT_BITS_TO_FLOAT), srcs[0]); + EMIT_BUF_WITH_RET(ctx, buf); + } else if (src->Register.File == TGSI_FILE_BUFFER) { snprintf(buf, 255, "%s = %s(int(%s.length()) << 2);\n", dsts[0], get_string(INT_BITS_TO_FLOAT), srcs[0]); EMIT_BUF_WITH_RET(ctx, buf); } @@ -2281,29 +2449,62 @@ translate_resq(struct dump_ctx *ctx, struct tgsi_full_instruction *inst, static int translate_atomic(struct dump_ctx *ctx, struct tgsi_full_instruction *inst, + struct source_info *sinfo, char srcs[4][255], char dsts[3][255]) { char buf[512]; const struct tgsi_full_src_register *src = &inst->Src[0]; const char *opname; - enum vrend_type_qualifier stypeprefix; - enum vrend_type_qualifier dtypeprefix; - enum vrend_type_qualifier stypecast; + enum vrend_type_qualifier stypeprefix = TYPE_CONVERSION_NONE; + enum vrend_type_qualifier dtypeprefix = TYPE_CONVERSION_NONE; + enum vrend_type_qualifier stypecast = TYPE_CONVERSION_NONE; bool is_cas; - char cas_str[64] = {}; - - stypeprefix = FLOAT_BITS_TO_UINT; - dtypeprefix = UINT_BITS_TO_FLOAT; - stypecast = UINT; + char cas_str[128] = {}; + + if (src->Register.File == TGSI_FILE_IMAGE) { + enum tgsi_return_type itype; + get_internalformat_string(ctx->images[sinfo->sreg_index].decl.Format, &itype); + switch (itype) { + default: + case TGSI_RETURN_TYPE_UINT: + stypeprefix = FLOAT_BITS_TO_UINT; + dtypeprefix = UINT_BITS_TO_FLOAT; + stypecast = UINT; + break; + case TGSI_RETURN_TYPE_SINT: + stypeprefix = FLOAT_BITS_TO_INT; + dtypeprefix = INT_BITS_TO_FLOAT; + stypecast = INT; + break; + case TGSI_RETURN_TYPE_FLOAT: + ctx->shader_req_bits |= SHADER_REQ_ES31_COMPAT; + stypecast = FLOAT; + break; + } + } else { + stypeprefix = FLOAT_BITS_TO_UINT; + dtypeprefix = UINT_BITS_TO_FLOAT; + stypecast = UINT; + } opname = get_atomic_opname(inst->Instruction.Opcode, &is_cas); if (!opname) return -1; if (is_cas) - snprintf(cas_str, 64, ", %s(%s(%s))", get_string(stypecast), get_string(stypeprefix), srcs[3]); - + snprintf(cas_str, 128, ", %s(%s(%s))", get_string(stypecast), get_string(stypeprefix), srcs[3]); + + if (src->Register.File == TGSI_FILE_IMAGE) { + bool is_ms = false; + enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx->images[sinfo->sreg_index].decl.Resource, &is_ms); + char ms_str[32] = {}; + if (is_ms) { + snprintf(ms_str, 32, ", int(%s.w)", srcs[1]); + } + snprintf(buf, 512, "%s = %s(imageAtomic%s(%s, %s(floatBitsToInt(%s))%s, %s(%s(%s))%s));\n", dsts[0], get_string(dtypeprefix), opname, srcs[0], get_string(coord_prefix), srcs[1], ms_str, get_string(stypecast), get_string(stypeprefix), srcs[2], cas_str); + EMIT_BUF_WITH_RET(ctx, buf); + } if (src->Register.File == TGSI_FILE_BUFFER) { snprintf(buf, 512, "%s = %s(atomic%s(%s[int(floatBitsToInt(%s)) >> 2], uint(%s(%s).x)%s));\n", dsts[0], get_string(dtypeprefix), opname, srcs[0], srcs[1], get_string(stypeprefix), srcs[2], cas_str); EMIT_BUF_WITH_RET(ctx, buf); @@ -2472,6 +2673,18 @@ get_destination_info(struct dump_ctx *ctx, snprintf(dsts[i], 255, "temp%d[addr0 + %d]%s", range->first, dst_reg->Register.Index - range->first, writemask); } else snprintf(dsts[i], 255, "temp%d[%d]%s", range->first, dst_reg->Register.Index - range->first, writemask); + } + else if (dst_reg->Register.File == TGSI_FILE_IMAGE) { + const char *cname = tgsi_proc_to_prefix(ctx->prog_type); + if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) { + int basearrayidx = lookup_image_array(ctx, dst_reg->Register.Index); + if (dst_reg->Register.Indirect) { + assert(dst_reg->Indirect.File == TGSI_FILE_ADDRESS); + snprintf(dsts[i], 255, "%simg%d[addr%d + %d]", cname, basearrayidx, dst_reg->Indirect.Index, dst_reg->Register.Index - basearrayidx); + } else + snprintf(dsts[i], 255, "%simg%d[%d]", cname, basearrayidx, dst_reg->Register.Index - basearrayidx); + } else + snprintf(dsts[i], 255, "%simg%d", cname, dst_reg->Register.Index); } else if (dst_reg->Register.File == TGSI_FILE_BUFFER) { const char *cname = tgsi_proc_to_prefix(ctx->prog_type); if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) { @@ -2740,6 +2953,18 @@ get_source_info(struct dump_ctx *ctx, snprintf(srcs[i], 255, "%ssamp%d%s", cname, src->Register.Index, swizzle); } sinfo->sreg_index = src->Register.Index; + } else if (src->Register.File == TGSI_FILE_IMAGE) { + const char *cname = tgsi_proc_to_prefix(ctx->prog_type); + if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) { + int basearrayidx = lookup_image_array(ctx, src->Register.Index); + if (src->Register.Indirect) { + assert(src->Indirect.File == TGSI_FILE_ADDRESS); + snprintf(srcs[i], 255, "%simg%d[addr%d + %d]", cname, basearrayidx, src->Indirect.Index, src->Register.Index - basearrayidx); + } else + snprintf(srcs[i], 255, "%simg%d[%d]", cname, basearrayidx, src->Register.Index - basearrayidx); + } else + snprintf(srcs[i], 255, "%simg%d%s", cname, src->Register.Index, swizzle); + sinfo->sreg_index = src->Register.Index; } else if (src->Register.File == TGSI_FILE_BUFFER) { const char *cname = tgsi_proc_to_prefix(ctx->prog_type); if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) { @@ -3526,7 +3751,7 @@ iter_instruction(struct tgsi_iterate_context *iter, return FALSE; break; case TGSI_OPCODE_LOAD: - ret = translate_load(ctx, inst, srcs, dsts); + ret = translate_load(ctx, inst, &sinfo, &dinfo, srcs, dsts, writemask); if (ret) return FALSE; break; @@ -3540,7 +3765,7 @@ iter_instruction(struct tgsi_iterate_context *iter, case TGSI_OPCODE_ATOMUMAX: case TGSI_OPCODE_ATOMIMIN: case TGSI_OPCODE_ATOMIMAX: - ret = translate_atomic(ctx, inst, srcs, dsts); + ret = translate_atomic(ctx, inst, &sinfo, srcs, dsts); if (ret) return FALSE; break; @@ -3751,6 +3976,136 @@ static void *emit_sampler_decl(struct dump_ctx *ctx, char *glsl_hdr, uint32_t i, return glsl_hdr; } +const char *get_internalformat_string(int virgl_format, enum tgsi_return_type *stype) +{ + switch (virgl_format) { + case PIPE_FORMAT_R11G11B10_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(r11f_g11f_b10f) "; + case PIPE_FORMAT_R10G10B10A2_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(rgb10_a2) "; + case PIPE_FORMAT_R10G10B10A2_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rgb10_a2ui) "; + case PIPE_FORMAT_R8_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(r8) "; + case PIPE_FORMAT_R8_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(r8_snorm) "; + case PIPE_FORMAT_R8_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(r8ui) "; + case PIPE_FORMAT_R8_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(r8i) "; + case PIPE_FORMAT_R8G8_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(rg8) "; + case PIPE_FORMAT_R8G8_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(rg8_snorm) "; + case PIPE_FORMAT_R8G8_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rg8ui) "; + case PIPE_FORMAT_R8G8_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rg8i) "; + case PIPE_FORMAT_R8G8B8A8_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(rgba8) "; + case PIPE_FORMAT_R8G8B8A8_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(rgba8_snorm) "; + case PIPE_FORMAT_R8G8B8A8_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rgba8ui) "; + case PIPE_FORMAT_R8G8B8A8_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rgba8i) "; + case PIPE_FORMAT_R16_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(r16) "; + case PIPE_FORMAT_R16_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(r16_snorm) "; + case PIPE_FORMAT_R16_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(r16ui) "; + case PIPE_FORMAT_R16_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(r16i) "; + case PIPE_FORMAT_R16_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(r16f) "; + case PIPE_FORMAT_R16G16_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(rg16) "; + case PIPE_FORMAT_R16G16_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(rg16_snorm) "; + case PIPE_FORMAT_R16G16_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rg16ui) "; + case PIPE_FORMAT_R16G16_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rg16i) "; + case PIPE_FORMAT_R16G16_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(rg16f) "; + case PIPE_FORMAT_R16G16B16A16_UNORM: + *stype = TGSI_RETURN_TYPE_UNORM; + return "layout(rgba16) "; + case PIPE_FORMAT_R16G16B16A16_SNORM: + *stype = TGSI_RETURN_TYPE_SNORM; + return "layout(rgba16_snorm) "; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(rgba16f) "; + case PIPE_FORMAT_R32_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(r32f) "; + case PIPE_FORMAT_R32_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(r32ui) "; + case PIPE_FORMAT_R32_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(r32i) "; + case PIPE_FORMAT_R32G32_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(rg32f) "; + case PIPE_FORMAT_R32G32_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rg32ui) "; + case PIPE_FORMAT_R32G32_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rg32i) "; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + *stype = TGSI_RETURN_TYPE_FLOAT; + return "layout(rgba32f) "; + case PIPE_FORMAT_R32G32B32A32_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rgba32ui) "; + case PIPE_FORMAT_R16G16B16A16_UINT: + *stype = TGSI_RETURN_TYPE_UINT; + return "layout(rgba16ui) "; + case PIPE_FORMAT_R16G16B16A16_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rgba16i) "; + case PIPE_FORMAT_R32G32B32A32_SINT: + *stype = TGSI_RETURN_TYPE_SINT; + return "layout(rgba32i) "; + case PIPE_FORMAT_NONE: + *stype = TGSI_RETURN_TYPE_UNORM; + return ""; + default: + *stype = TGSI_RETURN_TYPE_UNORM; + fprintf(stderr, "illegal format %d\n", virgl_format); + return ""; + } +} + static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr) { uint32_t i; @@ -4166,6 +4521,44 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr) } } + if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) { + for (i = 0; i < ctx->num_image_arrays; i++) { + int idx = ctx->image_arrays[i].first; + int is_shad = 0; + const char *stc; + char ptc; + const char *volatile_str = (ctx->images[idx].vflag) ? "volatile " : ""; + const char *writeonly = (ctx->images[idx].decl.Format) ? "" : "writeonly "; + const char *formatstr; + enum tgsi_return_type itype; + formatstr = get_internalformat_string(ctx->images[idx].decl.Format, &itype); + ptc = vrend_shader_samplerreturnconv(itype); + sname = tgsi_proc_to_prefix(ctx->prog_type); + stc = vrend_shader_samplertypeconv(ctx->images[i].decl.Resource, &is_shad); + snprintf(buf, 255, "%s%s%suniform %cimage%s %simg%d[%d];\n", formatstr, writeonly, volatile_str, ptc, stc, sname, idx, ctx->image_arrays[i].array_size); + STRCAT_WITH_RET(glsl_hdr, buf); + } + } else { + uint32_t mask = ctx->images_used_mask; + while (mask) { + int is_shad = 0; + const char *stc; + char ptc; + + i = u_bit_scan(&mask); + const char *volatile_str = (ctx->images[i].vflag) ? "volatile " : ""; + const char *writeonly = (ctx->images[i].decl.Format) ? "" : "writeonly "; + const char *formatstr; + enum tgsi_return_type itype; + formatstr = get_internalformat_string(ctx->images[i].decl.Format, &itype); + ptc = vrend_shader_samplerreturnconv(itype); + sname = tgsi_proc_to_prefix(ctx->prog_type); + stc = vrend_shader_samplertypeconv(ctx->images[i].decl.Resource, &is_shad); + snprintf(buf, 255, "%s%s%suniform %cimage%s %simg%d;\n", formatstr, writeonly, volatile_str, ptc, stc, sname, i); + STRCAT_WITH_RET(glsl_hdr, buf); + } + } + if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) { uint32_t mask = ctx->ssbo_used_mask; while (mask) { @@ -4262,6 +4655,8 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg, ctx.key = key; ctx.cfg = cfg; ctx.prog_type = -1; + ctx.num_image_arrays = 0; + ctx.image_arrays = NULL; ctx.num_sampler_arrays = 0; ctx.sampler_arrays = NULL; ctx.last_sampler_array_idx = -1; @@ -4284,7 +4679,8 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg, if (ctx.info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT)) require_glsl_ver(&ctx, 150); - if (ctx.info.indirect_files & (1 << TGSI_FILE_BUFFER)) { + if (ctx.info.indirect_files & (1 << TGSI_FILE_BUFFER) || + ctx.info.indirect_files & (1 << TGSI_FILE_IMAGE)) { require_glsl_ver(&ctx, 150); ctx.shader_req_bits |= SHADER_REQ_GPU_SHADER5; } @@ -4336,6 +4732,7 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg, sinfo->num_clip_out = has_prop ? ctx.num_clip_dist_prop : (ctx.num_clip_dist ? ctx.num_clip_dist : 8); sinfo->num_cull_out = has_prop ? ctx.num_cull_dist_prop : 0; sinfo->samplers_used_mask = ctx.samplers_used; + sinfo->images_used_mask = ctx.images_used_mask; sinfo->num_consts = ctx.num_consts; sinfo->num_ubos = ctx.num_ubo; memcpy(sinfo->ubo_idx, ctx.ubo_idx, ctx.num_ubo * sizeof(*ctx.ubo_idx)); @@ -4368,6 +4765,8 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg, sinfo->attrib_input_mask = ctx.attrib_input_mask; sinfo->sampler_arrays = ctx.sampler_arrays; sinfo->num_sampler_arrays = ctx.num_sampler_arrays; + sinfo->image_arrays = ctx.image_arrays; + sinfo->num_image_arrays = ctx.num_image_arrays; return glsl_final; fail: free(ctx.glsl_main); diff --git a/src/vrend_shader.h b/src/vrend_shader.h index a19da20..6bb671b 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -44,8 +44,14 @@ struct vrend_sampler_array { int sview_rtype; }; +struct vrend_image_array { + int first; + int array_size; +}; + struct vrend_shader_info { uint32_t samplers_used_mask; + uint32_t images_used_mask; uint32_t ssbo_used_mask; int num_consts; int num_inputs; @@ -73,6 +79,9 @@ struct vrend_shader_info { struct vrend_sampler_array *sampler_arrays; int num_sampler_arrays; + struct vrend_image_array *image_arrays; + int num_image_arrays; + struct pipe_stream_output_info so_info; struct vrend_interp_info *interpinfo;