r300g: fix RG/LATC1_SNORM by doing UNORM->SNORM conversion in the shader

This commit is contained in:
Marek Olšák 2011-04-05 06:21:26 +02:00
parent 20141d9efd
commit b3011ea60c
6 changed files with 123 additions and 36 deletions

View File

@ -22,6 +22,7 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
@ -34,6 +35,7 @@
#include "r300_screen.h"
#include "r300_fs.h"
#include "r300_reg.h"
#include "r300_texture.h"
#include "r300_tgsi_to_rc.h"
#include "radeon_code.h"
@ -148,7 +150,6 @@ static void get_external_state(
struct r300_textures_state *texstate = r300->textures_state.state;
struct r300_rs_state *rs = r300->rs_state.state;
unsigned i;
unsigned char *swizzle;
state->frag_clamp = rs ? rs->rs.clamp_fragment_color : 0;
@ -161,27 +162,37 @@ static void get_external_state(
continue;
}
t = r300_resource(texstate->sampler_views[i]->base.texture);
t = r300_resource(v->base.texture);
if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
state->unit[i].compare_mode_enabled = 1;
/* Pass depth texture swizzling to the compiler. */
if (texstate->sampler_views[i]) {
swizzle = texstate->sampler_views[i]->swizzle;
state->unit[i].depth_texture_swizzle =
RC_MAKE_SWIZZLE(swizzle[0], swizzle[1],
swizzle[2], swizzle[3]);
} else {
state->unit[i].depth_texture_swizzle = RC_SWIZZLE_XYZW;
}
/* Fortunately, no need to translate this. */
state->unit[i].texture_compare_func = s->state.compare_func;
}
state->unit[i].non_normalized_coords = !s->state.normalized_coords;
state->unit[i].convert_unorm_to_snorm =
v->base.format == PIPE_FORMAT_RGTC1_SNORM ||
v->base.format == PIPE_FORMAT_LATC1_SNORM;
/* Pass texture swizzling to the compiler, some lowering passes need it. */
if (v->base.format == PIPE_FORMAT_RGTC1_SNORM ||
v->base.format == PIPE_FORMAT_LATC1_SNORM) {
unsigned char swizzle[4];
util_format_combine_swizzles(swizzle,
util_format_description(v->base.format)->swizzle,
v->swizzle);
state->unit[i].texture_swizzle =
RC_MAKE_SWIZZLE(swizzle[0], swizzle[1],
swizzle[2], swizzle[3]);
} else if (state->unit[i].compare_mode_enabled) {
state->unit[i].texture_swizzle =
RC_MAKE_SWIZZLE(v->swizzle[0], v->swizzle[1],
v->swizzle[2], v->swizzle[3]);
}
/* XXX this should probably take into account STR, not just S. */
if (t->tex.is_npot) {

View File

@ -650,8 +650,13 @@ static uint32_t r300_get_border_color(enum pipe_format format,
if (util_format_is_compressed(format)) {
switch (format) {
case PIPE_FORMAT_RGTC1_SNORM:
case PIPE_FORMAT_RGTC1_UNORM:
case PIPE_FORMAT_LATC1_SNORM:
border_swizzled[0] = border_swizzled[0] < 0 ?
border_swizzled[0]*0.5+1 :
border_swizzled[0]*0.5;
/* Pass through. */
case PIPE_FORMAT_RGTC1_UNORM:
case PIPE_FORMAT_LATC1_UNORM:
/* Add 1/32 to round the border color instead of truncating. */
/* The Y component is used for the border color. */

View File

@ -39,6 +39,18 @@
#include "pipe/p_screen.h"
void util_format_combine_swizzles(unsigned char *dst,
const unsigned char *swz1,
const unsigned char *swz2)
{
unsigned i;
for (i = 0; i < 4; i++) {
dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
swz1[swz2[i]] : swz2[i];
}
}
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
const unsigned char *swizzle_view,
boolean dxtc_swizzle)
@ -61,10 +73,7 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
if (swizzle_view) {
/* Combine two sets of swizzles. */
for (i = 0; i < 4; i++) {
swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
swizzle_format[swizzle_view[i]] : swizzle_view[i];
}
util_format_combine_swizzles(swizzle, swizzle_format, swizzle_view);
} else {
memcpy(swizzle, swizzle_format, 4);
}
@ -171,17 +180,22 @@ uint32_t r300_translate_texformat(enum pipe_format format,
}
}
if (util_format_is_compressed(format) &&
dxtc_swizzle &&
format != PIPE_FORMAT_RGTC2_UNORM &&
format != PIPE_FORMAT_RGTC2_SNORM &&
format != PIPE_FORMAT_LATC2_UNORM &&
format != PIPE_FORMAT_LATC2_SNORM) {
result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
TRUE);
} else {
result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
FALSE);
/* Add swizzling. */
/* The RGTC1_SNORM and LATC1_SNORM swizzle is done in the shader. */
if (format != PIPE_FORMAT_RGTC1_SNORM &&
format != PIPE_FORMAT_LATC1_SNORM) {
if (util_format_is_compressed(format) &&
dxtc_swizzle &&
format != PIPE_FORMAT_RGTC2_UNORM &&
format != PIPE_FORMAT_RGTC2_SNORM &&
format != PIPE_FORMAT_LATC2_UNORM &&
format != PIPE_FORMAT_LATC2_SNORM) {
result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
TRUE);
} else {
result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
FALSE);
}
}
/* S3TC formats. */
@ -212,7 +226,6 @@ uint32_t r300_translate_texformat(enum pipe_format format,
switch (format) {
case PIPE_FORMAT_RGTC1_SNORM:
case PIPE_FORMAT_LATC1_SNORM:
result |= sign_bit[2];
case PIPE_FORMAT_LATC1_UNORM:
case PIPE_FORMAT_RGTC1_UNORM:
return R500_TX_FORMAT_ATI1N | result;

View File

@ -35,6 +35,10 @@ struct r300_texture_desc;
struct r300_resource;
struct r300_screen;
void util_format_combine_swizzles(unsigned char *dst,
const unsigned char *swz1,
const unsigned char *swz2);
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
const unsigned char *swizzle_view,
boolean dxtc_swizzle);

View File

@ -132,10 +132,10 @@ typedef enum {
struct r300_fragment_program_external_state {
struct {
/**
* If the sampler is used as a shadow sampler,
* this field contains swizzle depending on the depth texture mode.
* This field contains swizzle for some lowering passes
* (shadow comparison, unorm->snorm conversion)
*/
unsigned depth_texture_swizzle:12;
unsigned texture_swizzle:12;
/**
* If the sampler is used as a shadow sampler,
@ -172,6 +172,12 @@ struct r300_fragment_program_external_state {
* and right before texture fetch. The scaling factor is given by
* RC_STATE_R300_TEXSCALE_FACTOR. */
unsigned clamp_and_scale_before_fetch : 1;
/**
* Fetch RGTC1_SNORM or LATC1_SNORM as UNORM and convert UNORM -> SNORM
* in the shader.
*/
unsigned convert_unorm_to_snorm:1;
} unit[16];
unsigned frag_clamp:1;

View File

@ -48,7 +48,7 @@ static struct rc_src_register shadow_fail_value(struct r300_fragment_program_com
}
reg.Swizzle = combine_swizzles(reg.Swizzle,
compiler->state.unit[tmu].depth_texture_swizzle);
compiler->state.unit[tmu].texture_swizzle);
return reg;
}
@ -59,7 +59,7 @@ static struct rc_src_register shadow_pass_value(struct r300_fragment_program_com
reg.File = RC_FILE_NONE;
reg.Swizzle = combine_swizzles(RC_SWIZZLE_1111,
compiler->state.unit[tmu].depth_texture_swizzle);
compiler->state.unit[tmu].texture_swizzle);
return reg;
}
@ -256,7 +256,7 @@ int radeonTransformTEX(
inst_cmp->U.I.SrcReg[0].Index = tmp_sum;
inst_cmp->U.I.SrcReg[0].Swizzle =
combine_swizzles(RC_SWIZZLE_WWWW,
compiler->state.unit[inst->U.I.TexSrcUnit].depth_texture_swizzle);
compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle);
inst_cmp->U.I.SrcReg[pass] = shadow_pass_value(compiler, inst->U.I.TexSrcUnit);
inst_cmp->U.I.SrcReg[fail] = shadow_fail_value(compiler, inst->U.I.TexSrcUnit);
@ -411,6 +411,7 @@ int radeonTransformTEX(
inst->U.I.SrcReg[0].Index = temp;
}
/* NPOT -> POT conversion for 3D textures. */
if (inst->U.I.Opcode != RC_OPCODE_KIL &&
compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch) {
struct rc_instruction *inst_mov;
@ -440,6 +441,53 @@ int radeonTransformTEX(
scale_texcoords(compiler, inst, RC_STATE_R300_TEXSCALE_FACTOR);
}
/* Convert SNORM-encoded ATI1N sampled as UNORM to SNORM.
* Formula: dst = tex > 0.5 ? tex*2-2 : tex*2
*/
if (inst->U.I.Opcode != RC_OPCODE_KIL &&
compiler->state.unit[inst->U.I.TexSrcUnit].convert_unorm_to_snorm) {
unsigned two, two_swizzle;
struct rc_instruction *inst_mul, *inst_mad, *inst_cnd;
two = rc_constants_add_immediate_scalar(&c->Program.Constants, 2.35, &two_swizzle);
inst_mul = rc_insert_new_instruction(c, inst);
inst_mul->U.I.Opcode = RC_OPCODE_MUL;
inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
inst_mul->U.I.DstReg.Index = rc_find_free_temporary(c);
inst_mul->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
inst_mul->U.I.SrcReg[0].Index = rc_find_free_temporary(c); /* redirected TEX output */
inst_mul->U.I.SrcReg[1].File = RC_FILE_CONSTANT; /* 2 */
inst_mul->U.I.SrcReg[1].Index = two;
inst_mul->U.I.SrcReg[1].Swizzle = two_swizzle;
inst_mad = rc_insert_new_instruction(c, inst_mul);
inst_mad->U.I.Opcode = RC_OPCODE_MAD;
inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
inst_mad->U.I.DstReg.Index = rc_find_free_temporary(c);
inst_mad->U.I.SrcReg[0] = inst_mul->U.I.SrcReg[0]; /* redirected TEX output */
inst_mad->U.I.SrcReg[1] = inst_mul->U.I.SrcReg[1]; /* 2 */
inst_mad->U.I.SrcReg[2] = inst_mul->U.I.SrcReg[1]; /* 2 */
inst_mad->U.I.SrcReg[2].Negate = RC_MASK_XYZW;
inst_cnd = rc_insert_new_instruction(c, inst_mad);
inst_cnd->U.I.Opcode = RC_OPCODE_CND;
inst_cnd->U.I.SaturateMode = inst->U.I.SaturateMode;
inst_cnd->U.I.DstReg = inst->U.I.DstReg;
inst_cnd->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
inst_cnd->U.I.SrcReg[0].Index = inst_mad->U.I.DstReg.Index;
inst_cnd->U.I.SrcReg[0].Swizzle = compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle;
inst_cnd->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
inst_cnd->U.I.SrcReg[1].Index = inst_mul->U.I.DstReg.Index;
inst_cnd->U.I.SrcReg[1].Swizzle = compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle;
inst_cnd->U.I.SrcReg[2] = inst_mul->U.I.SrcReg[0]; /* redirected TEX output */
inst->U.I.SaturateMode = 0;
inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
inst->U.I.DstReg.Index = inst_mul->U.I.SrcReg[0].Index;
inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
}
/* Cannot write texture to output registers or with saturate (all chips),
* or with masks (non-r500). */
if (inst->U.I.Opcode != RC_OPCODE_KIL &&