Page 1 of 4 1234 LastLast
Results 1 to 10 of 39

Thread: Feedback: New SPIR-V common intermediate language used by both OpenCL 2.1 and Vulkan

  1. #1
    Administrator khronos's Avatar
    Join Date
    Jun 2002
    Location
    Montreal
    Posts
    86

    Feedback: New SPIR-V common intermediate language used by both OpenCL 2.1 and Vulkan

    The Khronos Group made another significant announcement, OpenCL 2.1 and Vulkan™, the new open standard API for high-efficiency access to graphics and compute on modern GPUs, are now sharing core intermediate language technologies resulting in SPIR-V; a revolution in the Khronos Standard Portable Intermediate Representation initially used by OpenCL™, now fully defined by Khronos with native support for shader and kernel features. SPIR-V splits the compiler chain, enabling high-level language front-ends to emit programs in a standardized intermediate form to be ingested by Vulkan or OpenCL drivers. Eliminating the need for a built-in high-level language source compiler significantly reduces driver complexity and will enable a diversity of language front-ends. Additionally, a standardized IR provides a measure of kernel IP protection, accelerated kernel load times and enables developers to use a common language front-end, improving kernel reliability and portability across multiple implementations.


    All feedback that is posted to this topic thread will be considered by the working group. We greatly appreciate what you have to say and the time you spent preparing your feedback.

  2. #2
    Junior Member
    Join Date
    Jan 2015
    Posts
    3
    Hello folks,

    First and foremost I'd like to congratulate and to tank you all about this incredible work!

    I have a few questions (/worries) about OpenCL++ specs and I'd like to know if these are because of lack of SPIR-V features or because somebody decide to restrict them in OpenCL++ specs.
    So, at page 37 of OpenCL++ specs I see the following restrictions:

    - The dynamic_cast operator (section 5.2.7)
    Is this a SPIR-V restriction? Is not a must to have, most probably c++ developers can survive without it, but, IMHO, there are cases where it can be quite useful.

    - Type identification (section 5.2.
    Same as dynamic_cast.

    - Recursive function calls (section 5.2.2, item 9)
    You mean I can create a recursive function? E.g. I can't compute Fibonaci number recursively? If my assumption is true (TBH I really hope is not!) then the question is: it is SPIR-V fault? It will be a quite annoying restriction even it will be OpenCL++ only restriction...

    - new and delete operators (sections 5.3.4, 5.3.5)
    Is this a SPIR-V restriction? Why can't I allocate/free memory at runtime?

    - goto statement (section 6.6)
    Is this a SPIR-V restriction?

    - register, thread_local storage qualifiers (section 7.1.1)
    These are not necessary unless GPU vendors will make use of them. IMHO it doesn't hurt if SPIR-V can handle them...

    - virtual function qualifier (section 7.1.2)
    - virtual functions and abstract classes (sections 10.3, 10.4)
    - function pointers (sections 8.3.5, 8.5.3)
    Is this a SPIR-V restriction? IMHO SPIR-V should handle them.

    - noexcept operator (section 5.3.7)
    - exception handling (section 15)
    I hope this is not SPIR-V restriction . Exceptions are quite common in all modern languages. If you want people to be able to write a shader in JavaScript,Python, etc. then they are used to use exceptions and they will find quite annoying if they can't use them.

  3. #3
    Senior Member
    Join Date
    Mar 2015
    Posts
    173
    Quote Originally Posted by bog_dan_ro View Post
    Hello folks,

    First and foremost I'd like to congratulate and to tank you all about this incredible work!

    I have a few questions (/worries) about OpenCL++ specs and I'd like to know if these are because of lack of SPIR-V features or because somebody decide to restrict them in OpenCL++ specs.
    So, at page 37 of OpenCL++ specs I see the following restrictions:

    - The dynamic_cast operator (section 5.2.7)
    Is this a SPIR-V restriction? Is not a must to have, most probably c++ developers can survive without it, but, IMHO, there are cases where it can be quite useful.


    - Type identification (section 5.2.
    Same as dynamic_cast.
    you are not allowed to redeclare the same type with a different IDs so each type is fully defined and unique

    conversion between primitive types are
    Quote Originally Posted by bog_dan_ro View Post
    - Recursive function calls (section 5.2.2, item 9)
    You mean I can create a recursive function? E.g. I can't compute Fibonaci number recursively? If my assumption is true (TBH I really hope is not!) then the question is: it is SPIR-V fault? It will be a quite annoying restriction even it will be OpenCL++ only restriction...
    recursion is possible as you can call forward declared functions (you need to specify the type of the function you are calling which is prototyped with the types at the top)

    however drivers/hardware can restrict the stack size such that you can only squeeze out 2 recursive calls
    Quote Originally Posted by bog_dan_ro View Post
    - new and delete operators (sections 5.3.4, 5.3.5)
    Is this a SPIR-V restriction? Why can't I allocate/free memory at runtime?
    OpVariable is a "new Type()" and OpVariableArray is a "new Type[n]"

    deallocation/deletion can happen implicitly by not using it anymore inside the scope

    besides that there is the OpLifetimeStart and OpLifetimeEnd in flow-control

    Quote Originally Posted by bog_dan_ro View Post
    - goto statement (section 6.6)
    Is this a SPIR-V restriction?
    no you can use random opBranches but that makes optimization harder as the compiler can't add the op*Merge opcodes to some flow control constructs

    Quote Originally Posted by bog_dan_ro View Post
    - register, thread_local storage qualifiers (section 7.1.1)
    These are not necessary unless GPU vendors will make use of them. IMHO it doesn't hurt if SPIR-V can handle them...

    - virtual function qualifier (section 7.1.2)
    - virtual functions and abstract classes (sections 10.3, 10.4)
    - function pointers (sections 8.3.5, 8.5.3)
    Is this a SPIR-V restriction? IMHO SPIR-V should handle them.
    I think you use the function IDs as first class object making them part of a struct type and opSelect between them

    This will be needed if you want to support sub routines in shaders (as you'd need to opLoad it from a variable)

    Quote Originally Posted by bog_dan_ro View Post
    - noexcept operator (section 5.3.7)
    - exception handling (section 15)
    I hope this is not SPIR-V restriction . Exceptions are quite common in all modern languages. If you want people to be able to write a shader in JavaScript,Python, etc. then they are used to use exceptions and they will find quite annoying if they can't use them.
    C has worked fine without exceptions,

    I think it was removed because the basic block assumption will be violated and remove some optimization options

  4. #4
    Quote Originally Posted by bog_dan_ro View Post
    I have a few questions (/worries) about OpenCL++ specs and I'd like to know if these are because of lack of SPIR-V features or because somebody decide to restrict them in OpenCL++ specs.
    I don't think you fully understand that the GPU computational space is decidedly limited in its capabilities, compared to what CPUs can do. This is dictated by hardware; if SPIR-V limits some form of execution, it is generally because those are the limits imposed by the hardware SPIR-V abstracts.

    These limitations are what binds OpenCL++'s language support, not SPIR-V. GPUs cannot handle C++ in all of its complexity, so the goal with OpenCL++ is to handle as much of C++ as GPUs can.

    That doesn't make GPU compute or OpenCL++ useless; it's quite useful in fact. But it's not reasonable to expect the same level of feature support as a CPU.

    At least not yet.

    I'll re-order your questions in my response:

    Quote Originally Posted by bog_dan_ro View Post
    - Recursive function calls (section 5.2.2, item 9)
    You mean I can create a recursive function? E.g. I can't compute Fibonaci number recursively? If my assumption is true (TBH I really hope is not!) then the question is: it is SPIR-V fault? It will be a quite annoying restriction even it will be OpenCL++ only restriction...
    The execution model of most GPUs does not include a stack, which is essential to implementing arbitrary recursion. I understand the desire for recursion and such, but it's not feasible on most modern GPUs.

    Quote Originally Posted by bog_dan_ro View Post
    - The dynamic_cast operator (section 5.2.7)
    - virtual function qualifier (section 7.1.2)
    - virtual functions and abstract classes (sections 10.3, 10.4)
    - function pointers (sections 8.3.5, 8.5.3)
    These all boil down to basically the same issue: the lack of function pointers. You can't really implement virtual functions/inheritance without function pointers. You can't have abstract classes if you don't have virtual functions. And there's no point in dynamic_cast if you can't have virtual functions/inheritance, since all of your types are static and known at compile-time.

    So it all comes down to not having function pointers. The problem is that GPUs don't work well with function pointers, since function pointers tend to rely on stack. And as previously stated, the execution model of most GPUs don't give you one.

    Quote Originally Posted by bog_dan_ro View Post
    - Type identification (section 5.2.
    Given the above restrictions... why would you need RTTI? If you can't have virtual functions and virtual base classes, then all your types are static. Thus, all types are known at compile-time.

    Also, RTTI would require bloating your executable with runtime type information.

    Quote Originally Posted by bog_dan_ro View Post
    - new and delete operators (sections 5.3.4, 5.3.5)
    Is this a SPIR-V restriction? Why can't I allocate/free memory at runtime?
    Because GPU compute elements can't allocate memory. You can provide them with memory buffers, and they can use those. But allocating actual memory is very much beyond their capabilities.

    Remember: the GPU execution model is many-core; you have hundreds of these small threads all executing at once, doing the same operations on different parts of memory. And memory allocation (from a shared pool, like GPU memory) is a highly single-threaded process. So every time one thread hits this mutex, any other thread that tries to allocate memory will have to stop and wait for that thread to finish.

    And remember: we're talking hundreds of threads.

    That's just not viable if you want anything remotely like performance. Which is why you're using OpenCL to begin with

    - goto statement (section 6.6)
    Is this a SPIR-V restriction?
    Only in the sense that SPIR-V doesn't have a generalized goto. It's much more of a "we don't want you to be able to jump around code arbitrarily," restriction. That is, even if SPIR-V did support it, I doubt OpenCL++ would.

    And in this case, it's not so much that GPUs can't handle general goto (probably). It's likely more that GPU vendors don't want users to be able to have the capability.

    - noexcept operator (section 5.3.7)
    - exception handling (section 15)
    I hope this is not SPIR-V restriction . Exceptions are quite common in all modern languages. If you want people to be able to write a shader in JavaScript,Python, etc. then they are used to use exceptions and they will find quite annoying if they can't use them.
    There are many "modern languages" that don't have exceptions, so they're hardly a linguistic requirement.

    Equally importantly... why would you want to write compute operations in a scripting language like JavaScript or Python? Compute operations would gain nothing from such an environment. As you've pointed out, memory allocation is not allowed, so you don't get the benefits of garbage collection. Nor can you do runtime compilation of new functions. Since function pointers aren't possible, you'll lose the ability to have first-class functions (so it's doubtful that you could even implement them). If you have to give up most of the advantages of the language just to be able to execute, why are you using that language?

    So really, the only reason to use these over something like C or C++ is syntactic preference. In which case, I'd say: "deal with it."

    Lastly, I'm curious as to exactly what you plan to do in OpenCL that you feel the need to have exceptions. While compute operations don't need to be tiny things, a single compute operation is usually not so gigantic that exceptions would be an essential means of error handling.

  5. #5
    Senior Member
    Join Date
    Mar 2015
    Posts
    173
    Quote Originally Posted by Alfonse Reinheart View Post
    These all boil down to basically the same issue: the lack of function pointers. You can't really implement virtual functions/inheritance without function pointers. You can't have abstract classes if you don't have virtual functions. And there's no point in dynamic_cast if you can't have virtual functions/inheritance, since all of your types are static and known at compile-time.

    So it all comes down to not having function pointers. The problem is that GPUs don't work well with function pointers, since function pointers tend to rely on stack. And as previously stated, the execution model of most GPUs don't give you one.
    So shader subroutine uniform support will need to be handled using opSelect on a uniform int?

  6. #6
    Quote Originally Posted by ratchet freak View Post
    So shader subroutine uniform support will need to be handled using opSelect on a uniform int?
    To the extent that people use shader subroutines, yes, you'd have to do something like that. Unless I missed something in the SPIR-V spec (which is entirely possible), there's no direct support for such functions.

  7. #7
    Junior Member
    Join Date
    Jan 2015
    Posts
    3
    I'd like to start with a clarification. I fully understand and I really don't mind if all these restrictions are for OpenCL++ 2.1 spec, because it's targeting past and present GPUs, however SPIR-V is not OpenCL++ and it shall not be tight related to past and present GPUs, instead the specs should have then future GPUs in mind (e.g. 10-20 years from now), it should be the technology that will push the things forward.

    Quote Originally Posted by ratchet freak View Post
    you are not allowed to redeclare the same type with a different IDs so each type is fully defined and unique

    conversion between primitive types are
    So, this is SPIR-V restriction, right?

    Quote Originally Posted by ratchet freak View Post
    recursion is possible as you can call forward declared functions (you need to specify the type of the function you are calling which is prototyped with the types at the top)

    however drivers/hardware can restrict the stack size such that you can only squeeze out 2 recursive calls
    Good to know that this is not an SPIR-V restriction.

    Quote Originally Posted by ratchet freak View Post
    OpVariable is a "new Type()" and OpVariableArray is a "new Type[n]"

    deallocation/deletion can happen implicitly by not using it anymore inside the scope

    besides that there is the OpLifetimeStart and OpLifetimeEnd in flow-control
    Hmm .. what if I want to create a function that computes something returns big result (e.g. a huge vector)? It will be copied twice?

    e.g.
    vector * compute_my_vector()
    {
    if(some_error)
    return nullptr;
    vector * ret = new vector;
    //....
    return vector;
    }


    Quote Originally Posted by ratchet freak View Post
    no you can use random opBranches but that makes optimization harder as the compiler can't add the op*Merge opcodes to some flow control constructs
    Good to know that this is not an SPIR-V restriction.

    Quote Originally Posted by ratchet freak View Post
    I think you use the function IDs as first class object making them part of a struct type and opSelect between them

    This will be needed if you want to support sub routines in shaders (as you'd need to opLoad it from a variable)
    Shall I understand that SPIR-V can't handle virtual functions, right?

    Quote Originally Posted by ratchet freak View Post
    C has worked fine without exceptions,

    I think it was removed because the basic block assumption will be violated and remove some optimization options
    Right, but SPIR-V is not C and you aim for a rich variety of frontends which are not C .
    IMHO will not hurt at all if SPIR-V will handle it. Of course OpenCL standard can explicitly specify that current GPUs drivers (because I don't see any reason why the GPU asm can't handle it) don't supports it and maybe in OpenCL 3.0 you'll add it.

    Quote Originally Posted by Alfonse Reinheart View Post
    I don't think you fully understand that the GPU computational space is decidedly limited in its capabilities, compared to what CPUs can do. This is dictated by hardware; if SPIR-V limits some form of execution, it is generally because those are the limits imposed by the hardware SPIR-V abstracts.

    These limitations are what binds OpenCL++'s language support, not SPIR-V. GPUs cannot handle C++ in all of its complexity, so the goal with OpenCL++ is to handle as much of C++ as GPUs can.
    IMHO SPIR-V should not limit anything. SPIR-V shall handle full C++ or any other language out there. The GPU limitations should come only from OpenCL standard. I really don't understand why SPIR-V needs to be bound to current drivers/GPUs capabilities...

    Quote Originally Posted by Alfonse Reinheart View Post
    That doesn't make GPU compute or OpenCL++ useless; it's quite useful in fact. But it's not reasonable to expect the same level of feature support as a CPU.

    At least not yet.
    At least not yet. That's what i'm talking about! So why limit SPIR-V?


    Quote Originally Posted by Alfonse Reinheart View Post
    The execution model of most GPUs does not include a stack, which is essential to implementing arbitrary recursion. I understand the desire for recursion and such, but it's not feasible on most modern GPUs.
    But we can't assume that in the future the situation will never change, right?

    Quote Originally Posted by Alfonse Reinheart View Post
    These all boil down to basically the same issue: the lack of function pointers. You can't really implement virtual functions/inheritance without function pointers. You can't have abstract classes if you don't have virtual functions. And there's no point in dynamic_cast if you can't have virtual functions/inheritance, since all of your types are static and known at compile-time.
    So it all comes down to not having function pointers. The problem is that GPUs don't work well with function pointers, since function pointers tend to rely on stack. And as previously stated, the execution model of most GPUs don't give you one.
    Given the above restrictions... why would you need RTTI? If you can't have virtual functions and virtual base classes, then all your types are static. Thus, all types are known at compile-time.
    Also, RTTI would require bloating your executable with runtime type information.
    Because GPU compute elements can't allocate memory. You can provide them with memory buffers, and they can use those. But allocating actual memory is very much beyond their capabilities.
    Remember: the GPU execution model is many-core; you have hundreds of these small threads all executing at once, doing the same operations on different parts of memory. And memory allocation (from a shared pool, like GPU memory) is a highly single-threaded process. So every time one thread hits this mutex, any other thread that tries to allocate memory will have to stop and wait for that thread to finish.
    And remember: we're talking hundreds of threads.
    That's just not viable if you want anything remotely like performance. Which is why you're using OpenCL to begin with
    Only in the sense that SPIR-V doesn't have a generalized goto. It's much more of a "we don't want you to be able to jump around code arbitrarily," restriction. That is, even if SPIR-V did support it, I doubt OpenCL++ would.
    And in this case, it's not so much that GPUs can't handle general goto (probably). It's likely more that GPU vendors don't want users to be able to have the capability.
    I understand that current GPUs/drivers don't have a stack and starting from that restrictions you've had to remove the other features, but all these restrictions for current GPUs and must come from OpenCL specs NOT from SPIR-V, because nobody knows, 10y from now, what GPUs/drivers will be capable of.

    Quote Originally Posted by Alfonse Reinheart View Post
    There are many "modern languages" that don't have exceptions, so they're hardly a linguistic requirement.
    I really don't know many general proposed language that was created after 2k and doesn't have exceptions. Actually besides Go which can return multiple types so you can still signal the problem, I don't know any other.

    Quote Originally Posted by Alfonse Reinheart View Post
    Equally importantly... why would you want to write compute operations in a scripting language like JavaScript or Python? Compute operations would gain nothing from such an environment. As you've pointed out, memory allocation is not allowed, so you don't get the benefits of garbage collection. Nor can you do runtime compilation of new functions. Since function pointers aren't possible, you'll lose the ability to have first-class functions (so it's doubtful that you could even implement them). If you have to give up most of the advantages of the language just to be able to execute, why are you using that language?

    So really, the only reason to use these over something like C or C++ is syntactic preference. In which case, I'd say: "deal with it."
    Why do you think it will be that wrong to use JavaScript, Python, etc. as frontends to write shaders/compute operations as long as they end-up as SPIR-V code? I thought that was the idea of using SPIR-V, to allow game engines (or other compiler/interpreters) to use whatever they want as front ends for shaders/compute operations. I don't see anything wrong that in the future web browsers will allow me to use JavaScript to write your shaders.

    Quote Originally Posted by Alfonse Reinheart View Post
    Lastly, I'm curious as to exactly what you plan to do in OpenCL that you feel the need to have exceptions. While compute operations don't need to be tiny things, a single compute operation is usually not so gigantic that exceptions would be an essential means of error handling.
    Exceptions can be heaven or/and hell, it just depends where and how they are used. Personally I like exceptions because they make my code looks cleaner, especially when I'm going to call lots of functions that might fail. But it really doesn't matter at all why, how and if I (or you) will use exceptions, because we can't assume that we know what's the best for everyone, IMHO what matters the most is that SPIR-V, as an open IL specification that can be used by any frontend, shall not limit the exceptions.

    SPIR-V shall have no limits at all, all the restrictions (device capabilities) shall come only from OpenCL/GLSL specs. It will quite unpleasant if in the future we'll see SPIR-V 2.0 not being compatible with the initial SPIR-V

    I really appreciate what you've done with SPIR-V, is a huge step forward, and I really hope my feedback will help and doesn't offend anyone.

  8. #8
    Junior Member
    Join Date
    Mar 2015
    Posts
    14
    One quick question:
    Is it "spir-vee" or "spir-five"?

  9. #9
    Senior Member
    Join Date
    Mar 2015
    Posts
    173
    According to the presentation live-stream it's spir-Vee (kinda logical since there wasn't a spir 3 or 4)

  10. #10
    Hmm .. what if I want to create a function that computes something returns big result (e.g. a huge vector)? It will be copied twice?
    What do the OpenCL++ and the C++14 specifications say? I can't say what OpenCL++ says, but I do know what C++14 says about this.

    You're trying to look at an intermediate language when thinking about the features of the higher-level language you're actually using. You shouldn't; the whole point of the high-level language is that it's an abstraction. What that language says happens is what happens; let the compiler deal with how to implement it in SPIR-V.

    IMHO SPIR-V should not limit anything. SPIR-V shall handle full C++ or any other language out there. The GPU limitations should come only from OpenCL standard. I really don't understand why SPIR-V needs to be bound to current drivers/GPUs capabilities...
    This sort of predicting-the-future has been tried. OpenGL did a whole lot of it. It made a lot of guesses about what future graphics hardware would look like.

    It got some things right, particularly early on. But as time passed, it got more and more wrong, to the point where OpenGL 2.0 has to develop an entirely new mechanism to deal with a new paradigm (ie: shader and program objects) that overrode large chunks of the API.

    Predicting the future is dangerous. Better to standardize what exists and what will exist in the near-term.

    SPIR-V is an intermediate language; you're not supposed to keep data in this form long-term. So if we get a SPIR-V 2.0 in 3 years that provides more features, no harm done. If they have to completely rebuild SPIR-V from the ground up, no harm done. They just change the intermediate representation, people patch their front end (and add new features to their languages), and everyone's happy.

    You never want to give people the idea that something will be widely supported unless it actually is widely supported. So if there's no support for it now or in the near future, it shouldn't be there.

    If Vulkan and OpenCL 2.1 wanted a future-proof intermediate language, they'd just use LLVM. But they didn't. SPIR-V is not meant to be the final, ultimate intermediate language for everything under the sun.

    It's meant for today and the next few years. When things change, so too will SPIR-V. Think of it as hardware-neutral assembly. As hardware changes, as it gets more features, so too does the assembly.

    Why do you think it will be that wrong to use JavaScript, Python, etc. as frontends to write shaders/compute operations as long as they end-up as SPIR-V code?
    I didn't say that it would be "wrong". I asked why you would want to. What advantage would you get from doing so, beside some small syntactic sugar?

    Python is a solid language because of its wide-ranging support, including modules for pretty much anything. It's a scripting language that has first-class functions with proper lexical scoping, the ability to compile itself within itself, and various other scripting features. When I consider starting a project and evaluate languages for use in that project, these are the things that matter when deciding to use Python or not.

    You get none of these advantages in a compute environment.

    Remember: your argument was that SPIR-V needed to support exceptions, so that "modern" languages can use them. My counter-argument is to ask why supporting that particular feature is so important, when SPIR-V also doesn't support most of the other reasons to use those languages to begin with.

    Or to put it another way, you can freely use JavaScript as your front-end language to SPIR-V. But you will not have most of the language features of JavaScript, since SPIR-V doesn't support compilation, first-class functions, etc. So why would having exceptions make the job of implementing such a language easier, when you already have to lobotomize the language just to make the syntax work?

Page 1 of 4 1234 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean