r300/compiler: Enable swizzle packing in the allocator for r300 and r400
This commit is contained in:
@@ -87,6 +87,18 @@ static const struct swizzle_data* lookup_native_swizzle(unsigned int swizzle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given swizzle is valid for r300/r400. In most situations
|
||||
* it is better to use r300_swizzle_is_native() which can be accesed via
|
||||
* struct radeon_compiler *c; c->SwizzleCaps->IsNative().
|
||||
*/
|
||||
int r300_swizzle_is_native_basic(unsigned int swizzle)
|
||||
{
|
||||
if(lookup_native_swizzle(swizzle))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given instruction supports the swizzle and negate
|
||||
|
||||
@@ -34,5 +34,6 @@ extern struct rc_swizzle_caps r300_swizzle_caps;
|
||||
|
||||
unsigned int r300FPTranslateRGBSwizzle(unsigned int src, unsigned int swizzle);
|
||||
unsigned int r300FPTranslateAlphaSwizzle(unsigned int src, unsigned int swizzle);
|
||||
int r300_swizzle_is_native_basic(unsigned int swizzle);
|
||||
|
||||
#endif /* __R300_FRAGPROG_SWIZZLE_H_ */
|
||||
|
||||
@@ -141,7 +141,11 @@ static unsigned int srcs_need_rewrite(const struct rc_opcode_info * info)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int adjust_channels(
|
||||
/**
|
||||
* @return A swizzle the results from converting old_swizzle using
|
||||
* conversion_swizzle
|
||||
*/
|
||||
unsigned int rc_adjust_channels(
|
||||
unsigned int old_swizzle,
|
||||
unsigned int conversion_swizzle)
|
||||
{
|
||||
@@ -197,7 +201,8 @@ void rc_pair_rewrite_writemask(
|
||||
|
||||
for (i = 0; i < info->NumSrcRegs; i++) {
|
||||
sub->Arg[i].Swizzle =
|
||||
adjust_channels(sub->Arg[i].Swizzle, conversion_swizzle);
|
||||
rc_adjust_channels(sub->Arg[i].Swizzle,
|
||||
conversion_swizzle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +212,7 @@ static void normal_rewrite_writemask_cb(
|
||||
struct rc_src_register * src)
|
||||
{
|
||||
unsigned int * new_mask = (unsigned int *)userdata;
|
||||
src->Swizzle = adjust_channels(src->Swizzle, *new_mask);
|
||||
src->Swizzle = rc_adjust_channels(src->Swizzle, *new_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -605,3 +610,27 @@ struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A conversion swizzle for converting from old_mask->new_mask
|
||||
*/
|
||||
unsigned int rc_make_conversion_swizzle(
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask)
|
||||
{
|
||||
unsigned int conversion_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);
|
||||
unsigned int old_idx;
|
||||
unsigned int new_idx = 0;
|
||||
for (old_idx = 0; old_idx < 4; old_idx++) {
|
||||
if (!GET_BIT(old_mask, old_idx))
|
||||
continue;
|
||||
for ( ; new_idx < 4; new_idx++) {
|
||||
if (GET_BIT(new_mask, new_idx)) {
|
||||
SET_SWZ(conversion_swizzle, old_idx, new_idx);
|
||||
new_idx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return conversion_swizzle;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ rc_swizzle rc_mask_to_swizzle(unsigned int mask);
|
||||
|
||||
unsigned swizzle_mask(unsigned swizzle, unsigned mask);
|
||||
|
||||
unsigned int rc_adjust_channels(
|
||||
unsigned int old_swizzle,
|
||||
unsigned int conversion_swizzle);
|
||||
|
||||
void rc_pair_rewrite_writemask(
|
||||
struct rc_pair_sub_instruction * sub,
|
||||
unsigned int conversion_swizzle);
|
||||
@@ -78,4 +82,8 @@ rc_opcode rc_get_flow_control_inst(struct rc_instruction * inst);
|
||||
struct rc_instruction * rc_match_endloop(struct rc_instruction * endloop);
|
||||
struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop);
|
||||
|
||||
unsigned int rc_make_conversion_swizzle(
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask);
|
||||
|
||||
#endif /* RADEON_PROGRAM_UTIL_H */
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "program/register_allocate.h"
|
||||
#include "ralloc.h"
|
||||
|
||||
#include "r300_fragprog_swizzle.h"
|
||||
#include "radeon_compiler.h"
|
||||
#include "radeon_compiler_util.h"
|
||||
#include "radeon_dataflow.h"
|
||||
@@ -232,6 +233,26 @@ static unsigned int is_derivative(rc_opcode op)
|
||||
return (op == RC_OPCODE_DDX || op == RC_OPCODE_DDY);
|
||||
}
|
||||
|
||||
static int find_class(
|
||||
struct rc_class * classes,
|
||||
unsigned int writemask,
|
||||
unsigned int max_writemask_count)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < RC_REG_CLASS_COUNT; i++) {
|
||||
unsigned int j;
|
||||
if (classes[i].WritemaskCount > max_writemask_count) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (classes[i].Writemasks[j] == writemask) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static enum rc_reg_class variable_get_class(
|
||||
struct rc_variable * variable,
|
||||
struct rc_class * classes)
|
||||
@@ -240,25 +261,48 @@ static enum rc_reg_class variable_get_class(
|
||||
unsigned int can_change_writemask= 1;
|
||||
unsigned int writemask = rc_variable_writemask_sum(variable);
|
||||
struct rc_list * readers = rc_variable_readers_union(variable);
|
||||
int class_index;
|
||||
|
||||
if (!variable->C->is_r500) {
|
||||
unsigned int mask_count = 0;
|
||||
struct rc_class c;
|
||||
/* The assumption here is that if an instruction has type
|
||||
* RC_INSTRUCTION_NORMAL then it is a TEX instruction.
|
||||
* r300 and r400 can't swizzle the result of a TEX lookup. */
|
||||
if (variable->Inst->Type == RC_INSTRUCTION_NORMAL) {
|
||||
writemask = RC_MASK_XYZW;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (GET_BIT(writemask, i)) {
|
||||
mask_count++;
|
||||
}
|
||||
|
||||
/* Check if it is possible to do swizzle packing for r300/r400
|
||||
* without creating non-native swizzles. */
|
||||
class_index = find_class(classes, writemask, 3);
|
||||
if (class_index < 0) {
|
||||
goto error;
|
||||
}
|
||||
/* XXX We should do swizzle packing for r300 and r400 here.
|
||||
* We need to figure out how not to create non-native
|
||||
* swizzles. */
|
||||
if (mask_count > 1) {
|
||||
can_change_writemask = 0;
|
||||
c = classes[class_index];
|
||||
for (i = 0; i < c.WritemaskCount; i++) {
|
||||
int j;
|
||||
unsigned int conversion_swizzle =
|
||||
rc_make_conversion_swizzle(
|
||||
writemask, c.Writemasks[i]);
|
||||
for (j = 0; j < variable->ReaderCount; j++) {
|
||||
unsigned int old_swizzle;
|
||||
unsigned int new_swizzle;
|
||||
struct rc_reader r = variable->Readers[j];
|
||||
if (r.Inst->Type == RC_INSTRUCTION_PAIR ) {
|
||||
old_swizzle = r.U.P.Arg->Swizzle;
|
||||
} else {
|
||||
old_swizzle = r.U.I.Src->Swizzle;
|
||||
}
|
||||
new_swizzle = rc_adjust_channels(
|
||||
old_swizzle, conversion_swizzle);
|
||||
if (!r300_swizzle_is_native_basic(new_swizzle)) {
|
||||
can_change_writemask = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!can_change_writemask) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,20 +329,18 @@ static enum rc_reg_class variable_get_class(
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < RC_REG_CLASS_COUNT; i++) {
|
||||
unsigned int j;
|
||||
if (!can_change_writemask && classes[i].WritemaskCount > 1) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (classes[i].Writemasks[j] == writemask) {
|
||||
return classes[i].Class;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc_error(variable->C, "Could not find class for index=%u mask=%u\n",
|
||||
|
||||
class_index = find_class(classes, writemask,
|
||||
can_change_writemask ? 3 : 1);
|
||||
if (class_index > -1) {
|
||||
return classes[class_index].Class;
|
||||
} else {
|
||||
error:
|
||||
rc_error(variable->C,
|
||||
"Could not find class for index=%u mask=%u\n",
|
||||
variable->Dst.Index, writemask);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int overlap_live_intervals_array(
|
||||
|
||||
@@ -44,24 +44,11 @@ void rc_variable_change_dst(
|
||||
unsigned int new_index,
|
||||
unsigned int new_writemask)
|
||||
{
|
||||
unsigned int new_idx, old_idx;
|
||||
unsigned int conversion_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);
|
||||
struct rc_variable * var_ptr;
|
||||
struct rc_list * readers;
|
||||
unsigned int old_mask = rc_variable_writemask_sum(var);
|
||||
|
||||
new_idx = 0;
|
||||
for (old_idx = 0; old_idx < 4; old_idx++) {
|
||||
if (!GET_BIT(old_mask, old_idx))
|
||||
continue;
|
||||
for ( ; new_idx < 4; new_idx++) {
|
||||
if (GET_BIT(new_writemask, new_idx)) {
|
||||
SET_SWZ(conversion_swizzle, old_idx, new_idx);
|
||||
new_idx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int conversion_swizzle =
|
||||
rc_make_conversion_swizzle(old_mask, new_writemask);
|
||||
|
||||
for (var_ptr = var; var_ptr; var_ptr = var_ptr->Friend) {
|
||||
if (var_ptr->Inst->Type == RC_INSTRUCTION_NORMAL) {
|
||||
|
||||
Reference in New Issue
Block a user