Hello Gert, (hello Nicolai, ;-))

do you have some 'work in progress' ready.
Then I'll put my Turks XT back in and test LS2015 (Farming Simulator 2015) under Wine. It show missing details (the driver (the player) and all the other people walking around) with current Mesa git code. I get the same 'Failed to build shader' reports like you in your
https://bugs.freedesktop.org/show_bug.cgi?id=99349

W'll start with your attachment
https://bugs.freedesktop.org/attachment.cgi?id=131683

Greetings,
Dieter

Am 18.06.2017 14:41, schrieb Gert Wollny:
Hello Nicolai,


Am Sonntag, den 18.06.2017, 12:05 +0200 schrieb Nicolai Hähnle:
  
>   if HAVE_XLIB_GLX
>   SUBDIRS += drivers/x11
> @@ -101,7 +101,7 @@ AM_CFLAGS = \
>    $(VISIBILITY_CFLAGS) \
>    $(MSVC2013_COMPAT_CFLAGS)
>   AM_CXXFLAGS = \
> -  $(LLVM_CFLAGS) \
> +        $(LLVM_CXXFLAGS) \

I kind of suspect that this might be a no-no. On the one hand it
makes sense, because it makes the use of CXXFLAGS consistent, but
it's a pretty significant build system change.
I understand that, but c++11 is just such an improvement.


At least separate it out into its own patch.
Okay,





>    $(VISIBILITY_CXXFLAGS) \
>    $(MSVC2013_COMPAT_CXXFLAGS)
>   
> diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
> index 21f9167bda..a68e9d2afe 100644
> --- a/src/mesa/Makefile.sources
> +++ b/src/mesa/Makefile.sources
> @@ -509,6 +509,8 @@ STATETRACKER_FILES = \
>    state_tracker/st_glsl_to_tgsi.h \
>    state_tracker/st_glsl_to_tgsi_private.cpp \
>    state_tracker/st_glsl_to_tgsi_private.h \
> +        state_tracker/st_glsl_to_tgsi_temprename.cpp \
> +  state_tracker/st_glsl_to_tgsi_temprename.h \

Inconsistent use of whitespace.

Then the whole patch needs to be re-arranged, i.e. the 
st_glsl_to_tgsi_private stuff,
This was a mistake when I was re-basing the patch.

and I agree with Emil that the tests 
should be separated out into their own patch.
I'm currently working on this.


BTW, you can and should use

git rebase -x "cd $builddir && make" $basecommit

to verify that you don't break the build in an intermediate patch.
Nice trick, thanks.


> +typedef int scope_idx;

Please remove this, it's an unnecessary and distracting abstraction
that  doesn't gain you anything.
Actually, with the refactoring it did the last two days it helped a
lot.


I consider the scopes back-reference here and in temp_access to be
bad  style.
I already got rid of them.

Think less object- and more data-oriented, then you won't need them.
Most of those helper functions should be members of 
tgsi_temp_lifetime -- and the getters/setters can be removed
entirely.  YAGNI.
I think with the new design that uses pointers into a pre-allocated
array the methods must stay where they are.


To first approximation, you should never use mutable. Those methods 
should not be const to begin with.
This is something else I actually didn't like and corrected already.

> +scope_idx
> +tgsi_temp_lifetime::make_scope(e_scope_type type, int id, int lvl,
> +                               int s_begin)const
> +{
> +   int idx = scopes.size();
> +   scopes.push_back(prog_scope(type, idx, id, lvl, s_begin,
> scopes));
> +   return idx;
> +}

AFAICS this overload is only used once. Please remove it.
Okay.

Use C-style comments.
Okay,

Also, this should probably have an assert, or can this really happen?
I don't think it can happen, an assert it is.


+      case TGSI_OPCODE_IF:
> +      case TGSI_OPCODE_UIF:{
> +         if (inst->src[0].file == PROGRAM_TEMPORARY) {
> +               acc[inst->src[0].index].append(line, acc_read,
> current);
> +         }
> +         scope_idx scope = make_scope(current, sct_if, if_id,
> nesting_lvl, line);

It's probably a good idea to have scopes start at line + 1.
Otherwise, 
it may be tempting to think that the read access of the IF condition 
happens inside the IF scope, at least based on the line numbers.

I don't think that's a problem. At least I can't think of a test case
that would trigger a problem with that.



> +      case TGSI_OPCODE_DEFAULT: {
> +         auto scope_type = (inst->op == TGSI_OPCODE_CASE) ?
> +                              sct_switch_case :
> sct_switch_default;
> +         if ( scopes[current].type() == sct_switch ) {

No spaces inside parenthesis (also elsewhere).
Okay.

> +            scope_stack.push(current);
> +            current = make_scope(current, scope_type,
> scopes[current].id(),
> +                                 nesting_lvl, line);
> +         }else{

Spaces around else (also elsewhere).
Okay.


No comment between if- and else-block.
Okay.



> +            scopes[current].set_continue(current, line);

You do need to distinguish between break and continue (at least for 
accuracy), because break allows you to skip over a piece of code 
indefinitely while continue doesn't. I.e.:

I risk to differ, in the worst case a CONT can act like it would be a
BRK, and because I have to handle the worst case it doesn't make sense
to distinguish between the two.



    BGNLOOP
       ...
          BRK/CONT
       ...
       MOV TEMP[i], ...
       ...
    ENDLOOP

If it's a CONT, then i is written unconditionally inside the loop.
While one would normally expect this, it is not guarantied. Think of a
shader like this:

...
varying int a;
varying float b;

int f(int a, float b) {...}
for (int i = 0; i< n; ++i ) {
   if (a && f(i, b))
      continue;
   ...
   x =
}

It may not be the best style. but it is possible.


+
> +         for (unsigned j = 0; j < inst->tex_offset_num_offset;
> j++) {
> +            if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY) {
> +               acc[inst->tex_offsets[j].index].append(line,
> acc_read, current);
> +            }
> +         }

You need to handle the reads before the writes. After all, you might
have a

    ADD TEMP[i], TEMP[i], ...

which may have to register as an undefined read.
I will add a test case, and correct the code accordingly.




> +
> +      } // end default
> +      } // end switch (op)

No end-of-scope comments.
okay,

>
> +scope_idx
> +prog_scope::get_parent_loop() const

Based on what it does, this should be renamed to something like 
get_innermost_loop.
Okay.


> +void temp_access::append(int line, e_acc_type acc, scope_idx idx)
> +{
> +   last_write = line;

Looks like last_write should be called last_access.

Initially I thought the same, but a last read is also (most of the
time) the last access, and it is handled differently then a write past
the last read, so i think that last_write catches it better.


> +   if (acc == acc_read) {
> +      last_read = line;
> +      last_read_scope = idx;
> +      if (undefined_read > line) {
> +         undefined_read = line;
> +         undefined_read_scope = idx;
> +      }

The way you're using it this is effectively just first_read, not 
undefined_read.

Indeed.



> +   } else {
> +      if (first_write == -1) {
> +         first_write = line;
> +         first_write_scope = idx;
> +
> +         // we write in an if-branch
> +         auto fw_ifthen_scope = scopes[idx].in_ifelse();
> +         if ((fw_ifthen_scope >= 0) &&
> scopes[fw_ifthen_scope].in_loop()) {
> +            // value not always written, in loops we must keep it
> +            keep_for_full_loop = true;
> +         } else {
> +            // same thing for switch-case
> +            auto fw_switch_scope = scopes[idx].in_switchcase();
> +            if (fw_switch_scope >= 0 &&
> scopes[fw_switch_scope].in_loop()) {
> +               keep_for_full_loop = true;
> +            }
> +         }

Simplify this by using an in_conditional() instead of in_ifelse + 
in_switchcase().
I was thinking about this, but I also thought that when I want to track
all code path later then I will have to distinguish the two again, but,
on the other hand, adding a method that combines the two is a no-
brainer.



> +
> +   /* Only written to, just make sure that renaming
> +    * doesn't reuse this register too early (corner
> +    * case is the one opcode with two destinations) */
> +   if (last_read_scope < 0) {
> +      return make_pair(first_write, first_write + 1);

What if there are multiple writes to the temporary?
Good catch! Next text case :)


> +   /* propagate lifetime also if there was a continue/break
> +    * in a loop and the write was after it (so it constitutes
> +    * a conditional write */

It's only conditional if there was a break. Continue doesn't make it 
conditional.
I think I made my argument.

+   /* propagate lifetimes before moving to upper scopes */
> +   if ((scopes[first_write_scope].type() == sct_loop) &&
> +       (keep_for_full_loop || (undefined_read < first_write))) {
> +      first_write = scopes[first_write_scope].begin();
> +      int lr = scopes[first_write_scope].end();
> +      if (last_read < lr)
> +         last_read = lr;
> +   }

What about:

    BGNLOOP
       ...
       BGNLOOP
          IF ...
             read TEMP[i]
          ENDIF
          write TEMP[i]
       ENDLOOP
       ...
    ENDLOOP

In this case, you don't set keep_for_full_loop, yet the lifetime
must extend for the entire _outer_ loop.
Another test case that needs to be added :)


I see two related problems in the code:

1. In this case, keep_for_full_loop needs to be set to true (because 
overwriting first_write in the code above means that the related
check below won't fire).


2. target_level is set to the inner loop even though it really needs
to be set to the outer loop.
Indeed.

Thanks a lot,
Gert
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to