Announcement

Collapse
No announcement yet.

HOWTO implement an OpenGL extension for Mesa

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • HOWTO implement an OpenGL extension for Mesa

    Quoting Agdr:

    Originally posted by Agdr
    I think the best way to improve things would be to find out how to attract more individual developers and companies to help in development of Mesa and Gallium (..).
    Perhaps some cool tutorial on how to make a game work by implementing a new OpenGL extension for Mesa, or adding a feature to r600g or nv50g would help in that (..).
    That's a great idea. I'd be interested in implementing OpenGL extensions. If only I could manage to figure out the gory details.

    Here's a rough plan how I'd go about adding an extension to r600g.

    Step 0: Read the FAQ

    Mesa FAQ. Join the mailing list.
    http://www.mesa3d.org/faq.html#part4

    Radeon Architecture
    http://dri.freedesktop.org/wiki/Radeon%25Architecture

    Gallium3d documentation, and whatever else you can find

    Step 1: Figure out what's missing

    Running an application I see this warning:
    EE r600_screen.c/r600_get_param:109 - r600: unknown param 9

    Looking at r600_screen.c r600_get_param, then at include/pipe/p_defines.h enum pipe_cap tells me that param 9 is
    PIPE_CAP_TIMER_QUERY.

    Step 2: Find out what this should do

    GL_EXT_timer_query
    http://www.opengl.org/registry/specs...imer_query.txt

    Step 3: Find out what the hardware offers

    http://www.x.org/docs/AMD/R6xx_3D_Registers.pdf

    Searching for "time" points to the Event Initiator.
    There are four instructions that return timestamps:
    * 04 - CACHE_FLUSH_TS
    * 20 - CACHE_FLUSH_AND_INV_TS_EVENT
    * 37 - CR_DONE_TS
    * 40 - BOTTOM_OF_PIPE_TS

    Quoting GL_EXT_timer_query spec, "In this extension, the timers start and stop when the BeginQuery/EndQuery commands reach the bottom of the rendering pipeline."
    Looks like 40 - BOTTOM_OF_PIPE_TS might be a good candidate.

    Step 4: Look for prior art

    Mathias Fröhlich, EXT_timer_query softpipe implementation
    http://www.mail-archive.com/mesa-dev.../msg00683.html

    So, there's no hardware implementation we could copy from. The software implementation isn't much help in writing the needed asynchronous query mechanism from scratch. But maybe there's such a mechanism in a similar extension?

    Quoting the spec, "This extension (..) uses the query object mechanisms first introduced in the occlusion query extension, which allow time intervals to be polled asynchronously by the application."

    Stephan Schmid and Alex Deucher, occlusion query support
    http://www.mail-archive.com/mesa-com.../msg11889.html

    Step 5: Implementation

    At this point, it looks like most of the work is copy and paste:

    Copy the occlusion query implementation.
    Replace ZPASS_DONE with BOTTOM_OF_PIPE_TS.
    Return timestamps instead of ZPASS counters.
    Add capabilities.

    Step 6: Test

    Looks like it's already there, no need to write from scratch

    Mathias Fröhlich and Brian Paul, Simple test for GL_EXT_timer_query
    http://www.mail-archive.com/mesa-dev.../msg00775.html

    Step 7: Submit to Mesa-dev

  • #2
    Nice post -- this is an interesting pursuit. Do you think there is sufficient room in the open source drivers for people without NDAs to start implementing hardware-accelerated OpenGL extensions for Gallium?

    I think the main impedance is that it's traditionally been difficult to accrue any domain knowledge about the implementation of hardware-accelerated graphics. Even for someone like Michael who knows all the lingo, knowing the lingo plus the C programming language isn't enough to be able to do something significant for Mesa.

    Then again, I used to think audio was a difficult-to-learn domain. Then I just started hacking on stuff and eventually I became good enough at it to know what I'm talking about most of the time.

    Maybe it's just the reputation of difficulty?

    Comment


    • #3
      Getting new hardware to work for the first time is pretty hard because the hardware doesn't tell you when you do something wrong, it just locks up or doesn't do anything. Once the driver is working, making it do new things that don't require new hardware interaction is more like normal software development.

      The current 3D driver stack is >90% common, hardware independent code (ie Mesa common code) if that helps. If you're interested, people will help you get up to speed on how the driver works today.

      Comment


      • #4
        There's not really anything you need an NDA to implement. All the information is available in the register specs and programming guides, you just have to put together what registers relate to the extension you want to implement. You just need a test app and some patience. Feel free to ask questions on the mesa and dri mailing lists; we are happy to help new developers.

        Comment


        • #5
          Great!

          Perhaps there needs to be some equivalent of kernelnewbies.org for open GPU development: maybe Phoronix could host it and/or help with that?
          Maybe it could also imitate LWN, with regular overviews of current development, and articles contributed by the developer themselves?
          Or perhaps LWN itself could expand with a "Graphics development" feature like the "Kernel Development" it already has?

          After all, if people read "kernel development", wouldn't they also read "graphics development", which is as complicated, and also comes with pretty pictures?

          There is already a lot of content disseminated over several blogs, freedesktop wikis, and mailing lists, often reported on by Phoronix, but maybe some newbie-oriented and developer oriented central place could help.

          What else could be done to increase contributions?

          Much more user friendly and comprehensive documentation for Radeons could possibly be very helpful, but the ATI open driver team seems to already have trouble keeping up, so it's probably best they work on releasing new stuff instead.

          Comment


          • #6
            By the way, note that reverse engineering is often much easier than you could think at first.

            The reason is that there are tools that let you run some OpenGL program on the proprietary driver, and get a list of the commands it sends to the hardware.

            By comparing the commands generated for code that uses a given extension with the ones for code that doesn't, you can often easily and sometimes trivally figure out how something is performed.

            You often literally get a text diff looking like this:
            + SET_REGISTER 0x2230 1
            + SET_REGISTER 0x2234 <parameter value I passed to OpenGL>

            or looking like this:
            - SET_REGISTER TEXTURE_SETUP_3 0x34507802
            + SET_REGISTER TEXTURE_SETUP_3 0x34517802

            In the first case, it clearly means that register 0x2230 is an enable boolean for the feature, and register 0x2234 is used to specify the parameter value.

            In the second case, bit 16 of TEXTURE_SETUP_3 is the bit that enables the feature in question.

            Only issue, apparently the "revenge" tool for reverse engineering fglrx only works for r100-r500 and hasn't been updated for r600+.
            Perhaps the docs and driver code are so good that no one felt the need to reverse engineer fglrx?

            Obviously reverse engineering a whole new GPU from scratch is much harder, but you don't usually need to do that.

            Comment


            • #7
              Originally posted by allquixotic View Post
              Do you think there is sufficient room in the open source drivers for people without NDAs to start implementing hardware-accelerated OpenGL extensions for Gallium?
              Absolutely.

              Originally posted by allquixotic View Post
              I think the main impedance is that it's traditionally been difficult to accrue any domain knowledge about the implementation of hardware-accelerated graphics. Even for someone like Michael who knows all the lingo, knowing the lingo plus the C programming language isn't enough to be able to do something significant for Mesa.

              Then again, I used to think audio was a difficult-to-learn domain. Then I just started hacking on stuff and eventually I became good enough at it to know what I'm talking about most of the time.

              Maybe it's just the reputation of difficulty?
              Understanding OpenGL extension specifications should be sufficient for implementing extensions in Mesa. If you don't know your hardware, you may try adding extensions to a software rasterizer first. Knowing something about 3D graphics helps a lot.

              I think reverse-engineering ATI hardware is a waste of time these days. It's just easier to ask somebody, or read docs.

              Comment


              • #8
                I'd like to add that GPU command stream analysis is not only useful for reverse engineering, but also for tracking down open driver bugs by looking for commits changing the command stream, to compare the command streams generated by two drivers to figure out, and to develop immature hardware without locking up the hardware every time.

                In general, the tools used are:
                - mmiotrace, which logs all writes and reads from PCI registers: used to log the register read/writes by the kernel driver and X driver. Included in the mainstream kernel
                - valgrind-mmt, which logs all writes and reads from PCI registers generated by an userspace application.
                - renouveau, which dumps the command stream of the nVidia Linux OpenGL driver
                - revenge which dumps the command stream of the ATI Linux OpenGL driver
                - patches to libdrm that dump the command stream of the open drivers
                - renouveau-parse (and perhaps rules-ng-ng tools) to convert hexadecimal data into readable register offset/value pairs for known registers for nVidia cards
                - radeondb (and maybe others?) to convert hexadecimal data into readable register offset/value pairs for known registers for nVidia cards

                Also, there should be ways to use virtualization software with PCI Express passthrough and perhaps IO-MMUs to trace the Windows drivers, but I'm not sure about the specifics, and this is not usually done since reverse engineering the Linux drivers is much easier (and they are mostly shared code anyway for both nVidia and ATI).

                And you can use IDA Pro or equivalent tools to disassemble and decompile the proprietary drivers, but this is also not usually done, since it is not worth the hugely increased difficulty and time over reading command streams.

                For example, on http://nouveau.freedesktop.org/tests/, you can find a repository of command streams generated by the nVidia drivers.

                So, the HOWTO for reverse engineering OpenGL features is as follows:
                1. Check if the proprietary driver supports the extension. Otherwise, give up, or figure out how to emulate it in terms of other functionality (usually, this means the hardware itself doesn't support it directly).
                2. If the feature is not trivial, look for feature lists, public documentation, whitepapers, game development guides, tech presentations about the feature from the GPU manufacturer to know what exactly the hardware supports and maybe get some juicy details too
                3. Get a reverse engineering tool like renouveau or revenge
                4. Check if there is already a test for your feature
                5. If not:
                5a. Find some demo or test that makes use of the feature, and check that it works on the proprietary driver. If you cannot find any, write one yourself.
                5b. Find the most similar renouveau/revenge test, and modify it with code from the test/demo.
                5c. If applicable, either do two rendering passes, one with and one without a feature, or otherwise make it a compile option
                6. Run renouveau/revenge on the proprietary driver to get a trace (or use an existing trace if the test was already available)
                7. Run the parsing tool on the trace to get it as human readable as possible
                8. Compare command streams with and without the feature (either from the two passes of your tests, or comparing with other tests or other versions of your tests). Either use manual comparison, or "diff" if applicable.
                9. Figure out how the hardware works. If necessary, modify the test to add runs with different parameters, until you get a complete picture
                10. Add the registers you just reverse engineered to the relevant header and/or register database
                11. If necessary, enhance Mesa and Gallium core to support the new extension or feature. You may also want to implement it in softpipe if not available.
                12. Implement the extension in the open hardware driver
                13. If necessary, experiment with different values and different cases to get a better understanding
                14. Write a test for the feature if not already present in mesa-demos and piglit, and submit it
                15. Check that the tests have with no regression, and that the tests for the new feature now pass
                16. Submit your work

                Comment


                • #9
                  Originally posted by marek View Post
                  I think reverse-engineering ATI hardware is a waste of time these days. It's just easier to ask somebody, or read docs.
                  Good to know!

                  Anyway, in some sense, reverse engineering is literally asking the proprietary driver itself what you should do, and you are guaranteed to get the correct answer.

                  The problem, of course, is that the answer is specific for a given set of parameters, and will need manual generalization (sometimes from multiple data points) to be useful.

                  Comment


                  • #10
                    Originally posted by Agdr View Post
                    Much more user friendly and comprehensive documentation for Radeons could possibly be very helpful...
                    I think you'll see more enthusiasm for documentation once the Great Re-architecture is finished and documentation stops becoming obsolte within a few weeks of writing it. Most of it is done; the main open issue is moving the default 3D drivers onto the Gallium3D framework.

                    Originally posted by Agdr View Post
                    ...but the ATI open driver team seems to already have trouble keeping up, so it's probably best they work on releasing new stuff instead.
                    I don't really understand why you're saying this, given that between ATI/AMD and community developers they have nearly caught up on 8 years of new product introduction (r3xx came out in 2002) in a bit over 3 years.

                    Comment


                    • #11
                      Originally posted by Agdr View Post
                      9. Figure out how the hardware works. If necessary, modify the test to add runs with different parameters, until you get a complete picture
                      This one is the hard part

                      Comment


                      • #12
                        Originally posted by bridgman View Post
                        I don't really understand why you're saying this, given that between ATI/AMD and community developers they have nearly caught up on 8 years of new product introduction (r3xx came out in 2002) in a bit over 3 years.
                        Sorry, I think I made a poor choice of words. I meant to say you are currently behind, not that you are not accelerating and going to fix that.

                        In particular, there is the basic Evergreen support, and then I believe there are several undocumented areas like DirectX 11 tessellation and hull/domain shader dispatch, hardware MMU, demand paging and multiple context support (if any exists), compute shader dispatch, whatever other new features Evergreen has not already documented in the ISA docs, and perhaps holes in the less advanced stuff too.

                        Also, documentation and initial support for the next architecture refresh ("Southern Islands"?), and the next new architecture, so that people interested in open source can start sending money to you sooner.

                        Comment


                        • #13
                          I don't think it's worth writing an excessive amount of documentation by 10 developers just to get maybe 2 new hobbyist contributors.

                          This is how to get started and quickly get to know Mesa well:
                          - Know OpenGL and shaders.
                          - If you know OpenGL and shaders, you will get to know the Gallium3D interface pretty quickly (look at gallium docs and headers).
                          - Learn what's between the Mesa core (src/mesa/main), which *is* OpenGL, and Gallium3D (src/gallium/include/pipe). You will find out it's the mesa state tracker (src/mesa/state_tracker). Learn how it works by reading code.
                          - Look at code of a few gallium drivers, see how they are structured.
                          - Look at some commits to see how new extensions are added.
                          - Look at some commits to see how to change the Gallium3D interface to add a new feature, and what else needs to be done to make that feature supported in the entire stack.
                          - Understand that you are NOT expected to know everything.

                          This is how I started:
                          - Read Gallium headers, make sure you understand it.
                          - Read the driver you are interested in.
                          - Look for things that can be improved or fixed in the driver and send patches, without knowing anything else about Mesa, kernel DRM, DDX etc. (you'll learn that stuff as time goes by anyway)

                          And finally, the discuss-to-the-death approach doesn't work well if you also want to have some time for coding.

                          Comment


                          • #14
                            Originally posted by marek View Post
                            This is how to get started and quickly get to know Mesa well:
                            - Know OpenGL and shaders.
                            - If you know OpenGL and shaders, you will get to know the Gallium3D interface pretty quickly (look at gallium docs and headers).
                            - Learn what's between the Mesa core (src/mesa/main), which *is* OpenGL, and Gallium3D (src/gallium/include/pipe). You will find out it's the mesa state tracker (src/mesa/state_tracker). Learn how it works by reading code.
                            - Look at code of a few gallium drivers, see how they are structured.
                            - Look at some commits to see how new extensions are added.
                            - Look at some commits to see how to change the Gallium3D interface to add a new feature, and what else needs to be done to make that feature supported in the entire stack.
                            - Understand that you are NOT expected to know everything.
                            Thanks! Looks like a plan.

                            Originally posted by Agdr View Post
                            I'd like to add that GPU command stream analysis is not only useful for reverse engineering, but also for tracking down open driver bugs by looking for commits changing the command stream, to compare the command streams generated by two drivers to figure out, and to develop immature hardware without locking up the hardware every time.

                            In general, the tools used are:
                            - mmiotrace, which logs all writes and reads from PCI registers: used to log the register read/writes by the kernel driver and X driver. Included in the mainstream kernel
                            - valgrind-mmt, which logs all writes and reads from PCI registers generated by an userspace application.
                            - renouveau, which dumps the command stream of the nVidia Linux OpenGL driver
                            - revenge which dumps the command stream of the ATI Linux OpenGL driver
                            - patches to libdrm that dump the command stream of the open drivers
                            - renouveau-parse (and perhaps rules-ng-ng tools) to convert hexadecimal data into readable register offset/value pairs for known registers for nVidia cards
                            - radeondb (and maybe others?) to convert hexadecimal data into readable register offset/value pairs for known registers for nVidia cards
                            Great, thanks! I recently contemplated dumping copies of IB buffers that lock up the GPU to debugfs as binary blobs.

                            I'm primarily interested in enabling native applications to run with open drivers.

                            Comment


                            • #15
                              btw. those can be fixed easily, cuz seems to be static values, depending on card family, just need to find exact value and add them

                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 43 - PIPE_CAP_MAX_FS_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 44 - PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 45 - PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 46 - PIPE_CAP_MAX_FS_TEX_INDIRECTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 48 - PIPE_CAP_MAX_FS_INPUTS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 50 - PIPE_CAP_MAX_FS_TEMPS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 51 - PIPE_CAP_MAX_FS_ADDRS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 49 - PIPE_CAP_MAX_FS_CONSTS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 53 - PIPE_CAP_MAX_VS_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 54 - PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 55 - PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 56 - PIPE_CAP_MAX_VS_TEX_INDIRECTIONS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 58 - PIPE_CAP_MAX_VS_INPUTS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 60 - PIPE_CAP_MAX_VS_TEMPS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 61 - PIPE_CAP_MAX_VS_ADDRS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 59 - PIPE_CAP_MAX_VS_CONSTS
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 63 - PIPE_CAP_GEOMETRY_SHADER4
                              EE r600_screen.c/r600_get_param:110 - r600: unknown param 64 - PIPE_CAP_DEPTH_CLAMP

                              Comment

                              Working...
                              X