[Mesa-dev] [PATCH 10/11] clover: Add function for building a clover::module for non-TGSI targets
Tom Stellard
thomas.stellard at amd.com
Mon May 14 11:06:35 PDT 2012
On Mon, May 14, 2012 at 05:19:10PM +0200, Francisco Jerez wrote:
> Tom Stellard <tstellar at gmail.com> writes:
>
> > On Sun, May 13, 2012 at 04:10:50PM +0200, Francisco Jerez wrote:
> >> Tom Stellard <tstellar at gmail.com> writes:
> >>
> >> > On Sun, May 13, 2012 at 12:40:43AM +0200, Francisco Jerez wrote:
> >> >>[...]
> >> >> I can think of two different ways this could work (your solution would
> >> >> be somewhere in between):
> >> >>
> >> >> - The r600g LLVM back-end could support some well-defined output object
> >> >> format (e.g. the one implemented by the clover::module classes), like
> >> >> most of the other LLVM back-ends. You probably want to do this
> >> >> anyway if you want to be able to compile CL programs off-line. If
> >> >> you do it this way, the state tracker will just call clang to
> >> >> completion using the appropriate target and pass the generated
> >> >> machine code to the pipe driver.
> >> >>
> >> >> If you think supporting different hardware versions with different
> >> >> ISAs would be a problem under this scheme, we could have another
> >> >> compute cap that would determine a specific variant of the ISA.
> >> >>
> >> >
> >> > I think this is the most practical of these two options. However, the
> >> > biggest draw back of this solution is that if a target uses a backend that
> >> > is not a part of the LLVM tree (the r600 backend is not in the LLVM tree,
> >> > but I'm working on getting it in), the backend would have to be included
> >> > as a part of clover and drivers using LLVM for other state tracker would
> >> > end up with one copy of their LLVM backend in clover and another in the
> >> > driver.
> >>
> >> Apparently it's already standard practice in LLVM to build back-ends as
> >> separate object files. I don't see why you couldn't build the r600
> >> back-end as a shared library. There's no reason for it to be duplicated
> >> in the source tree or the address space of the process it's running in.
> >>
> >
> > I don't think this will work if clover and the back-end link
> > statically to the LLVM libraries, which is what Mesa does by default.
> > LLVM relies on global pointers to identify float types within
> > a module, so it doesn't work to pass a module between shared libraries that
> > have each linked separately with LLVM, which is what will be happening
> > if the Clang frontend and the backend live in separate shared objects.
> >
>
> I don't think that's going to be a problem. If you do it this way the
> state tracker will be generating r600 machine code directly and there
> should be no pointer identifiers being leaked through the gallium API.
>
> But, anyway, I think you want to link to the r600 back-end from the
> target instead of linking from the state tracker and pipe driver, that
> way you make sure you're only linking once.
>
> >
> >> > I guess this might be able to work, but I'm not really sure why doing
> >> > it this way would be better than what is implemented in this patch.
> >> >
> >> I just think it would be useful by itself to have the r600 back-end able
> >> to emit machine code in a specific object file format, and at the same
> >> time, by doing so you avoid driver-specific code in the state tracker
> >> that does one thing or another depending on the hardware it's running
> >> on, which seems like a layering violation to me.
> >
> > State trackers already use caps to do different things depending on
> > what hardware it's running. So, I'm not really sure why using
> > PIPE_SHADER_CAP_PREFFERED_IR is any different.
> >
>
> I'm aware, but the fact that we're already doing it elsewhere doesn't
> mean it's a good practice if it can be avoided.
>
> If it turns out it can't be avoided, IMHO, any driver caps that affect
> the state tracker behaviour should have a well-defined meaning
> independent from the pipe driver that is running behind, i.e. a state
> tracker should never have to do: "if (r600) { /* do something */ } else
> { /* do something else */ }".
>
I agree with you here. Just so I'm clear, when you say you don't want
"if (r600) { /* do something */ } else { /* do something else */ }"
are you referring to this block of code:
module
clover::compile_program_llvm(const compat::string &source,
const compat::string &target) {
if (target == compat::string("TGSI")) {
#if 0
build_binary(source, target, "cl_input");
module m = load_binary("cl_input.o");
std::remove("cl_input.o");
return m;
#else
return module();
} else {
return build_module_llvm(source, target, "cl_input");
}
#endif
}
If so, would it be better if this decision was based on the value of
PIPE_SHADER_CAP_PREFFERED_IR?
> >>
> >> >> - Another option would be to forget about driver-specific IRs in the
> >> >> compute API. The pipe driver would have the choice between TGSI and
> >> >> LLVM, if it wants LLVM, the state tracker would do roughly what
> >> >> you're doing here using some sort of "identity" LLVM target that
> >> >> would do nothing but describing the peculiarities of the hardware
> >> >> (e.g. endianness, widths of the supported primitive types), which in
> >> >> turn would be queried from the pipe driver using compute caps.
> >> >>
> >> >
> >> > This is the way I thought it would work initially, but the only way to
> >> > describe a target to Clang is by using the target triple, so passing a
> >> > list of caps into Clang is not going to work.
> >> >
> >> Why not? You're in control of the back-end, maybe I'm missing something
> >> but I don't see why the state tracker couldn't provide all the required
> >> parameters to the back-end as it's instantiated.
> >>
> >
> > Clang doesn't consult the backend when it converts OpenCL C to LLVM IR,
> > so passing extra information to the backend won't help. We need to pass
> > target information directly to Clang and the only way to do this is via
> > the target triple.
> >
> >
> >> If this is impossible for some reason, can't we encode these parameters
> >> in the processor variant part of the target triple? Aren't these
> >> parameters supposed to be encoded as a target description string at some
> >> point anyway?
> >>
> >
> > The target description string is one of the attributes on the TargetInfo
> > class in Clang, but there are others as well. Take a look at the
> > Targets.cpp file in Clang and you'll see what I'm talking about:
> > http://clang.llvm.org/doxygen/Targets_8cpp-source.html
> >
> >
> >> >> Personally I think the latter would be closer to ideal, but I guess it
> >> >> would also involve more work...
> >> >
> >> > My preference is to keep this patch as is. At this point, I'm not
> >> > really sure why the proposed alternate solutions would be better than
> >> > the current implementation, and I think if we want to support out of
> >> > tree backends, we will need to at least have the option of doing it this
> >> > way.
> >> >
> >> What bothers me of this solution is that you're pumping bytecode using a
> >> generic representation, but in a non-generic way, that isn't going to be
> >> useful for drivers other than r600 that want compute programs in the
> >> same representation -- at least not without a number of driver-specific
> >> ad-hoc changes in both LLVM and the CL state tracker.
> >>
> >
> > This is exactly what other state trackers do. They produce a generic
> > representation (TGSI) in a non-generic way. For example, st/mesa might
> > produce a TGSI fragment shader that uses indirect addressing for r600g,
> > but the TGSI representation of the shader is not generic. That TGSI
> > program will not run on r300g, because that driver does not support
> > indirect addressing.
>
> I didn't mean that all the code produced by the state tracker should be
> able to run on any hardware, I meant that whatever means you use to
> generate that code should be made as reusable for other drivers as
> possible.
>
> >> I'm fine with the CL state tracker giving out code in LLVM IR, but, if
> >> it does, I really think it makes no sense for it to even know it's
> >> running on r600.
> >>
> > Even though LLVM is a generic representation it's not always possible
> > to produce an LLVM bitcode program that is guaranteed to run on every
> > target, so if we use LLVM IR it will have to some knowledge about that
> > target on which it will executed.
> >
>
> Yes, what we are discussing is how to pass this information from the
> pipe driver to the compiler. If you don't want to fix clang, and you
> don't like my other proposal either, I'd consider separating the driver
> cap that determines the IR from the one that determines the target,
> until we have a generic way to pass the target description to the
> compiler.
>
I agree that having separate caps for the IR and the target is a good
idea. This is what I was proposing in the previous discussion about
this http://lists.freedesktop.org/archives/mesa-dev/2012-April/020959.html
Maybe we can revisit this discussion. What do you think about limiting
the values of PIPE_SHADER_CAP_PREFFERED_IR to {TGSI, LLVM, NATIVE} and
then adding a cap like PIPE_SHADER_CAP_LLVM_TARGET that returns the name
of the target (e.g. r600 for r600g)
-Tom
> >
> >> > Even though I prefer this solution, ultimately I want to come up with
> >> > something that works for everyone even if it isn't exactly what I
> >> > proposed. So, I hope we will be able to work something out.
> >> >
> >> > -Tom
> >
> > -Tom
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list