[Mesa-dev] [PATCH 09/17] st/mesa: implement glBitmap shader transformation using tgsi_transform_shader
Marek Olšák
maraeo at gmail.com
Mon Oct 5 18:26:22 PDT 2015
From: Marek Olšák <marek.olsak at amd.com>
---
src/mesa/Makefile.sources | 1 +
src/mesa/state_tracker/st_cb_bitmap.c | 145 ----------------------
src/mesa/state_tracker/st_cb_bitmap.h | 11 +-
src/mesa/state_tracker/st_cb_bitmap_shader.c | 174 +++++++++++++++++++++++++++
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 78 ------------
src/mesa/state_tracker/st_glsl_to_tgsi.h | 3 -
src/mesa/state_tracker/st_program.c | 34 ++++--
7 files changed, 202 insertions(+), 244 deletions(-)
create mode 100644 src/mesa/state_tracker/st_cb_bitmap_shader.c
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 0915594..8eb43ce 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -415,6 +415,7 @@ STATETRACKER_FILES = \
state_tracker/st_cache.h \
state_tracker/st_cb_bitmap.c \
state_tracker/st_cb_bitmap.h \
+ state_tracker/st_cb_bitmap_shader.c \
state_tracker/st_cb_blit.c \
state_tracker/st_cb_blit.h \
state_tracker/st_cb_bufferobjects.c \
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 230eba8..bb6dfe8 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -108,151 +108,6 @@ struct bitmap_cache
/**
- * Make fragment program for glBitmap:
- * Sample the texture and kill the fragment if the bit is 0.
- * This program will be combined with the user's fragment program.
- */
-static struct st_fragment_program *
-make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex)
-{
- struct st_context *st = st_context(ctx);
- struct st_fragment_program *stfp;
- struct gl_program *p;
- GLuint ic = 0;
-
- p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!p)
- return NULL;
-
- p->NumInstructions = 3;
-
- p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
- if (!p->Instructions) {
- ctx->Driver.DeleteProgram(ctx, p);
- return NULL;
- }
- _mesa_init_instructions(p->Instructions, p->NumInstructions);
-
- /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
- p->Instructions[ic].Opcode = OPCODE_TEX;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_TEX0;
- p->Instructions[ic].TexSrcUnit = samplerIndex;
- p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
- ic++;
-
- /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
- p->Instructions[ic].Opcode = OPCODE_KIL;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
-
- if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
- p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
-
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
- ic++;
-
- /* END; */
- p->Instructions[ic++].Opcode = OPCODE_END;
-
- assert(ic == p->NumInstructions);
-
- p->InputsRead = VARYING_BIT_TEX0;
- p->OutputsWritten = 0x0;
- p->SamplersUsed = (1 << samplerIndex);
-
- stfp = (struct st_fragment_program *) p;
- stfp->Base.UsesKill = GL_TRUE;
-
- return stfp;
-}
-
-
-static struct gl_program *
-make_bitmap_fragment_program_glsl(struct st_context *st,
- struct st_fragment_program *orig,
- GLuint samplerIndex)
-{
- struct gl_context *ctx = st->ctx;
- struct st_fragment_program *fp = (struct st_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
-
- if (!fp)
- return NULL;
-
- get_bitmap_visitor(fp, orig->glsl_to_tgsi, samplerIndex);
- return &fp->Base.Base;
-}
-
-
-static int
-find_free_bit(uint bitfield)
-{
- int i;
- for (i = 0; i < 32; i++) {
- if ((bitfield & (1 << i)) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-
-/**
- * Combine basic bitmap fragment program with the user-defined program.
- * \param st current context
- * \param fpIn the incoming fragment program
- * \param fpOut the new fragment program which does fragment culling
- * \param bitmap_sampler sampler number for the bitmap texture
- */
-void
-st_make_bitmap_fragment_program(struct st_context *st,
- struct gl_fragment_program *fpIn,
- struct gl_fragment_program **fpOut,
- GLuint *bitmap_sampler)
-{
- struct st_fragment_program *bitmap_prog;
- struct st_fragment_program *stfpIn = (struct st_fragment_program *) fpIn;
- struct gl_program *newProg;
- uint sampler;
-
- /*
- * Generate new program which is the user-defined program prefixed
- * with the bitmap sampler/kill instructions.
- */
- sampler = find_free_bit(fpIn->Base.SamplersUsed);
-
- if (stfpIn->glsl_to_tgsi)
- newProg = make_bitmap_fragment_program_glsl(st, stfpIn, sampler);
- else {
- bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler);
-
- newProg = _mesa_combine_programs(st->ctx,
- &bitmap_prog->Base.Base,
- &fpIn->Base);
- /* done with this after combining */
- st_reference_fragprog(st, &bitmap_prog, NULL);
- }
-
-#if 0
- {
- printf("Combined bitmap program:\n");
- _mesa_print_program(newProg);
- printf("InputsRead: 0x%x\n", newProg->InputsRead);
- printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
- _mesa_print_parameter_list(newProg->Parameters);
- }
-#endif
-
- /* return results */
- *fpOut = (struct gl_fragment_program *) newProg;
- *bitmap_sampler = sampler;
-}
-
-
-/**
* Copy user-provide bitmap bits into texture buffer, expanding
* bits into texels.
* "On" bits will set texels to 0x0.
diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h
index b4254ca..dc7e5cb 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.h
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -31,6 +31,7 @@
#include "main/compiler.h"
+#include <stdbool.h>
struct dd_function_table;
struct st_context;
@@ -47,13 +48,11 @@ extern void
st_destroy_bitmap(struct st_context *st);
extern void
-st_make_bitmap_fragment_program(struct st_context *st,
- struct gl_fragment_program *fpIn,
- struct gl_fragment_program **fpOut,
- GLuint *bitmap_sampler);
-
-extern void
st_flush_bitmap_cache(struct st_context *st);
+extern const struct tgsi_token *
+st_get_bitmap_shader(const struct tgsi_token *tokens,
+ unsigned sampler_index,
+ bool use_texcoord, bool swizzle_xxxx);
#endif /* ST_CB_BITMAP_H */
diff --git a/src/mesa/state_tracker/st_cb_bitmap_shader.c b/src/mesa/state_tracker/st_cb_bitmap_shader.c
new file mode 100644
index 0000000..cddea36
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap_shader.c
@@ -0,0 +1,174 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2015 Advanced Micro Devices, Inc.
+ * Copyright 2007 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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 "st_cb_bitmap.h"
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_debug.h"
+
+struct tgsi_bitmap_transform {
+ struct tgsi_transform_context base;
+ struct tgsi_shader_info info;
+ unsigned sampler_index;
+ bool use_texcoord;
+ bool swizzle_xxxx;
+ bool first_instruction_emitted;
+};
+
+static inline struct tgsi_bitmap_transform *
+tgsi_bitmap_transform(struct tgsi_transform_context *tctx)
+{
+ return (struct tgsi_bitmap_transform *)tctx;
+}
+
+static void
+transform_instr(struct tgsi_transform_context *tctx,
+ struct tgsi_full_instruction *current_inst)
+{
+ struct tgsi_bitmap_transform *ctx = tgsi_bitmap_transform(tctx);
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+ unsigned i, semantic;
+ int texcoord_index = -1;
+
+ if (ctx->first_instruction_emitted) {
+ tctx->emit_instruction(tctx, current_inst);
+ return;
+ }
+
+ ctx->first_instruction_emitted = true;
+
+ /* Add TEMP[0] if it's missing. */
+ if (ctx->info.file_max[TGSI_FILE_TEMPORARY] == -1) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ /* Add TEXCOORD[0] if it's missing. */
+ semantic = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
+ TGSI_SEMANTIC_GENERIC;
+ for (i = 0; i < ctx->info.num_inputs; i++) {
+ if (ctx->info.input_semantic_name[i] == semantic &&
+ ctx->info.input_semantic_index[i] == 0) {
+ texcoord_index = i;
+ break;
+ }
+ }
+
+ if (texcoord_index == -1) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.Name = semantic;
+ decl.Declaration.Interpolate = 1;
+ decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
+ decl.Range.First = decl.Range.Last = ctx->info.num_inputs;
+ texcoord_index = ctx->info.num_inputs;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ /* Declare the sampler. */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.Range.First = decl.Range.Last = ctx->sampler_index;
+ tctx->emit_declaration(tctx, &decl);
+
+ /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ inst.Instruction.Texture = 1;
+ inst.Texture.Texture = TGSI_TEXTURE_2D;
+
+ inst.Instruction.NumDstRegs = 1;
+ inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
+ inst.Dst[0].Register.Index = 0;
+ inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
+
+ inst.Instruction.NumSrcRegs = 2;
+ inst.Src[0].Register.File = TGSI_FILE_INPUT;
+ inst.Src[0].Register.Index = texcoord_index;
+ inst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X;
+ inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Z;
+ inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_W;
+ inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
+ inst.Src[1].Register.Index = ctx->sampler_index;
+
+ tctx->emit_instruction(tctx, &inst);
+
+ /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
+ inst.Instruction.NumDstRegs = 0;
+ inst.Instruction.NumSrcRegs = 1;
+
+ inst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
+ inst.Src[0].Register.Index = 0;
+ inst.Src[0].Register.Negate = 1;
+ inst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X;
+ if (ctx->swizzle_xxxx) {
+ inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X;
+ inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_X;
+ } else {
+ inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Z;
+ inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_W;
+ }
+ tctx->emit_instruction(tctx, &inst);
+
+ /* And emit the instruction we got. */
+ tctx->emit_instruction(tctx, current_inst);
+}
+
+const struct tgsi_token *
+st_get_bitmap_shader(const struct tgsi_token *tokens,
+ unsigned sampler_index,
+ bool use_texcoord, bool swizzle_xxxx)
+{
+ struct tgsi_bitmap_transform ctx;
+ struct tgsi_token *newtoks;
+ int newlen;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.base.transform_instruction = transform_instr;
+ ctx.sampler_index = sampler_index;
+ ctx.use_texcoord = use_texcoord;
+ ctx.swizzle_xxxx = swizzle_xxxx;
+ tgsi_scan_shader(tokens, &ctx.info);
+
+ newlen = tgsi_num_tokens(tokens) + 20;
+ newtoks = tgsi_alloc_tokens(newlen);
+ if (!newtoks)
+ return NULL;
+
+ tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base);
+ return newtoks;
+}
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 1488ea0..a54ee17 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -4466,84 +4466,6 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
fp->glsl_to_tgsi = v;
}
-/**
- * Make fragment program for glBitmap:
- * Sample the texture and kill the fragment if the bit is 0.
- * This program will be combined with the user's fragment program.
- *
- * Based on make_bitmap_fragment_program in st_cb_bitmap.c.
- */
-extern "C" void
-get_bitmap_visitor(struct st_fragment_program *fp,
- glsl_to_tgsi_visitor *original, int samplerIndex)
-{
- glsl_to_tgsi_visitor *v = new glsl_to_tgsi_visitor();
- struct st_context *st = st_context(original->ctx);
- struct gl_program *prog = &fp->Base.Base;
- st_src_reg coord, src0;
- st_dst_reg dst0;
- glsl_to_tgsi_instruction *inst;
-
- /* Copy attributes of the glsl_to_tgsi_visitor in the original shader. */
- v->ctx = original->ctx;
- v->prog = prog;
- v->shader_program = NULL;
- v->shader = NULL;
- v->glsl_version = original->glsl_version;
- v->native_integers = original->native_integers;
- v->options = original->options;
- v->next_temp = original->next_temp;
- v->num_address_regs = original->num_address_regs;
- v->samplers_used = prog->SamplersUsed = original->samplers_used;
- v->indirect_addr_consts = original->indirect_addr_consts;
- memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));
- v->num_immediates = original->num_immediates;
-
- /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
- coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type);
- src0 = v->get_temp(glsl_type::vec4_type);
- dst0 = st_dst_reg(src0);
- inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, dst0, coord);
- inst->sampler.index = samplerIndex;
- inst->sampler_array_size = 1;
- inst->tex_target = TEXTURE_2D_INDEX;
-
- prog->InputsRead |= VARYING_BIT_TEX0;
- prog->SamplersUsed |= (1 << samplerIndex); /* mark sampler as used */
- v->samplers_used |= (1 << samplerIndex);
-
- /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
- src0.negate = NEGATE_XYZW;
- if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
- src0.swizzle = SWIZZLE_XXXX;
- inst = v->emit_asm(NULL, TGSI_OPCODE_KILL_IF, undef_dst, src0);
-
- /* Now copy the instructions from the original glsl_to_tgsi_visitor into the
- * new visitor. */
- foreach_in_list(glsl_to_tgsi_instruction, inst, &original->instructions) {
- glsl_to_tgsi_instruction *newinst;
- st_src_reg src_regs[4];
-
- if (inst->dst[0].file == PROGRAM_OUTPUT)
- prog->OutputsWritten |= BITFIELD64_BIT(inst->dst[0].index);
-
- for (int i = 0; i < 4; i++) {
- src_regs[i] = inst->src[i];
- if (src_regs[i].file == PROGRAM_INPUT)
- prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index);
- }
-
- newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2], src_regs[3]);
- newinst->tex_target = inst->tex_target;
- newinst->sampler_array_size = inst->sampler_array_size;
- }
-
- /* Make modifications to fragment program info. */
- prog->Parameters = _mesa_clone_parameter_list(original->prog->Parameters);
- count_resources(v, prog);
- fp->glsl_to_tgsi = v;
-}
-
/* ------------------------- TGSI conversion stuff -------------------------- */
struct label {
unsigned branch_target;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h
index c29fc76..dcdfbeb 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.h
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h
@@ -58,9 +58,6 @@ void free_glsl_to_tgsi_visitor(struct glsl_to_tgsi_visitor *v);
void get_pixel_transfer_visitor(struct st_fragment_program *fp,
struct glsl_to_tgsi_visitor *original,
int scale_and_bias, int pixel_maps);
-void get_bitmap_visitor(struct st_fragment_program *fp,
- struct glsl_to_tgsi_visitor *original,
- int samplerIndex);
GLboolean st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 7a6720c..fba661b 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -567,18 +567,7 @@ st_translate_fragment_program(struct st_context *st,
assert(!(key->bitmap && key->drawpixels));
memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
- if (key->bitmap) {
- /* glBitmap drawing */
- struct gl_fragment_program *fp; /* we free this temp program below */
-
- st_make_bitmap_fragment_program(st, &stfp->Base,
- &fp, &variant->bitmap_sampler);
-
- variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
- stfp = st_fragment_program(fp);
- deleteFP = GL_TRUE;
- }
- else if (key->drawpixels) {
+ if (key->drawpixels) {
/* glDrawPixels drawing */
struct gl_fragment_program *fp; /* we free this temp program below */
@@ -892,6 +881,27 @@ st_translate_fragment_program(struct st_context *st,
fprintf(stderr, "mesa: cannot emulate deprecated features\n");
}
+ /* glBitmap */
+ if (key->bitmap) {
+ const struct tgsi_token *tokens;
+
+ variant->bitmap_sampler = ffs(~stfp->Base.Base.SamplersUsed) - 1;
+
+ tokens = st_get_bitmap_shader(variant->tgsi.tokens,
+ variant->bitmap_sampler,
+ st->needs_texcoord_semantic,
+ st->bitmap.tex_format ==
+ PIPE_FORMAT_L8_UNORM);
+
+ if (tokens) {
+ tgsi_free_tokens(variant->tgsi.tokens);
+ variant->tgsi.tokens = tokens;
+ variant->parameters =
+ _mesa_clone_parameter_list(stfp->Base.Base.Parameters);
+ } else
+ fprintf(stderr, "mesa: cannot create a shader for glBitmap\n");
+ }
+
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/);
debug_printf("\n");
--
2.1.4
More information about the mesa-dev
mailing list