aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-05-11 23:42:43 +0200
committerGitHub <noreply@github.com>2023-05-11 23:42:43 +0200
commit04d7728350cbd04dd86cd894e906c98673e3f9a7 (patch)
tree08e8c7dd495d1c4c6fcf5f7ba6b4b10693dc42f6 /doc
parenteaec942f56ceec9c14de5c4185a02602abadd50a (diff)
parent58a8306d24fe29d965aa8b40ddc37c3163c0a2f9 (diff)
downloadpsn00bsdk-04d7728350cbd04dd86cd894e906c98673e3f9a7.tar.gz
Merge pull request #70 from Lameguy64/v0.23-wip
Header cleanups, PCDRV, more safety checks, libc and mkpsxiso fixes (v0.23)
Diffstat (limited to 'doc')
-rw-r--r--doc/drawing_queue.md105
-rw-r--r--doc/toolchain.md42
2 files changed, 130 insertions, 17 deletions
diff --git a/doc/drawing_queue.md b/doc/drawing_queue.md
new file mode 100644
index 0000000..4fa83f7
--- /dev/null
+++ b/doc/drawing_queue.md
@@ -0,0 +1,105 @@
+
+# GPU drawing queue
+
+`libpsxgpu` manages access to the GPU by implementing a software driven queue.
+This queue, separate from the GPU's internal command FIFO, allows for high-level
+management of GPU operations such as display list sending, VRAM image uploads
+and framebuffer readback, in a similar way to the drawing queue system
+implemented behind the scenes by the official SDK.
+
+The queue is managed internally by the library and can hold up to 16 drawing
+operations ("DrawOps"). Each DrawOp is represented by a pointer to a function,
+alongside any arguments to be passed to it. Whenever the GPU is idle,
+`libpsxgpu` fetches a DrawOp from the queue and calls its respective function,
+which should then proceed to actually send commands to the GPU or set up and
+start a DMA transfer. `DrawSync()` can be called to wait for the queue to become
+empty or get its current length, while `DrawSyncCallback()` may be used to
+register a callback that will be invoked once the GPU is idle and no more
+DrawOps are pending.
+
+Completion of each DrawOp (and transition of the GPU from busy to idle state) is
+signalled through one of two means:
+
+- the DMA channel 2 IRQ, fired automatically by the DMA unit when a data
+ transfer such as a VRAM upload or a display list has finished executing;
+- the GPU IRQ, triggered manually using the `GP0(0x1f)` command or the `DR_IRQ`
+ primitive.
+
+Note that the end of a DMA transfer does not necessarily imply that the GPU has
+finished executing all commands; the last command issued may not yet be done,
+hence the ability to use the GPU IRQ instead is provided as a more reliable way
+to detect the completion of certain commands.
+
+## Built-in DrawOps
+
+The library includes a number of built-in DrawOps for the most common use cases.
+The following APIs are wrappers around DrawOps:
+
+- `DrawBuffer()` and `DrawBufferIRQ()` queue a new DrawOp to start a DMA
+ transfer in chunked mode (sending one word at a time) with the specified
+ starting address and number of words. `DrawBuffer2()` and `DrawBufferIRQ2()`
+ are the underlying DrawOp functions respectively.
+- `DrawOTag()` and `DrawOTagIRQ()` queue a new DrawOp to start a DMA transfer in
+ linked-list mode with the specified starting address, with `DrawOTag2()` and
+ `DrawOTagIRQ2()` being the respective DrawOp functions.
+- `PutDrawEnv()`, `PutDrawEnvFast()`, `DrawOTagEnv()` and `DrawOTagEnvIRQ()`
+ insert drawing environment setup commands as the first (or only) item in a
+ display list, then proceed to pass it to `DrawOTag()`. The setup packet
+ linked into the display list is stored as part of the `DRAWENV` structure.
+- `LoadImage()` and `StoreImage()` copy the provided coordinates into a
+ temporary buffer, then proceed to enqueue a DrawOp to actually start the VRAM
+ transfer. The synchronous variants of these APIs are `LoadImage2()` and
+ `StoreImage2()` respectively.
+- `MoveImage()` saves the provided coordinates into a temporary buffer, then
+ enqueues a DrawOp that will issue a `GP0(0x80)` VRAM blitting command. As
+ this command is handled entirely by the GPU with no DMA transfers involved,
+ the GPU IRQ is used to detect its completion.
+
+## Custom DrawOps
+
+Unlike the official SDK, `libpsxgpu` exposes the drawing queue by providing a
+way to enqueue arbitrary custom DrawOps. This can be useful for profiling
+purposes or to work around specific GPU bugs (see the use cases section).
+
+Custom DrawOps can be pushed into the queue by calling `EnqueueDrawOp()` and
+passing a pointer to the callback function in charge of issuing the DrawOp's
+commands to the GPU, as well as up to 3 arguments to be passed through to it.
+The function must:
+
+- call `SetDrawOpType()` to let the library know which type of IRQ it shall wait
+ for before moving onto the next DrawOp (either `DRAWOP_TYPE_DMA` or
+ `DRAWOP_TYPE_GPU_IRQ`);
+- wait until the GPU is ready to accept commands by polling the status bits in
+ `GPU_STAT` and make sure DMA channel 2 is also idle before proceeding;
+- issue any commands to the GPU's GP0 register and/or set up a DMA transfer,
+ terminating them with a `GP0(0x1f)` IRQ command if appropriate.
+
+Note that DrawOps are called from within the exception handler's context and
+must thus not block for significant periods of time, manipulate COP0 registers
+or wait for any IRQs to occur. They are also restricted from manipulating the
+drawing queue by e.g. calling `EnqueueDrawOp()`, `DrawOTag()` or any other
+function that enqueues a DrawOp.
+
+## Use cases
+
+### Scissoring commands
+
+The GPU provides commands to set the origin of all X/Y coordinates passed to it
+as well as a scissoring region, all pixels outside of which are automatically
+masked out during drawing. These commands are issued to the GP0 register and can
+be inserted in a display list through the `DR_OFFSET` and `DR_AREA` primitives,
+however they will *not* go through the GPU's command FIFO like most other
+primitives. They will instead take effect immediately, resulting in graphical
+glitches if the GPU is already busy processing a drawing command (i.e. if they
+are not the very first commands in a display list).
+
+The software-driven drawing queue provides a way around this. By splitting up a
+frame's display list into multiple chunks, one for each scissoring command
+issued, it is possible to always place scissoring commands at the beginning of a
+chunk. Each chunk can be terminated with a `DR_IRQ` primitive and queued for
+drawing using `DrawOTagIRQ()` to ensure the GPU goes idle before the next chunk
+is sent, preventing scissoring commands from being received by the GPU while
+busy.
+
+-----------------------------------------
+_Last updated on 2023-05-11 by spicyjpeg_
diff --git a/doc/toolchain.md b/doc/toolchain.md
index 8e28c24..9b65720 100644
--- a/doc/toolchain.md
+++ b/doc/toolchain.md
@@ -28,6 +28,7 @@ tested extensively:
- ~~GCC 7.4.0 with binutils 2.31~~ (the linker fails to build PS1 DLLs)
- GCC **11.1.0** with binutils **2.36**
- GCC **11.2.0** with binutils **2.37**
+- GCC **12.2.0** with binutils **2.40**
If you wish to pick an older GCC release but don't know which binutils version
it requires, see [here](https://wiki.osdev.org/Cross-Compiler_Successful_Builds)
@@ -78,7 +79,7 @@ for a compatibility table.
```bash
../binutils-<VERSION>/configure \
--prefix=/usr/local/mipsel-none-elf --target=mipsel-none-elf \
- --disable-docs --disable-nls --with-float=soft
+ --disable-docs --disable-nls --disable-werror --with-float=soft
```
Replace `<VERSION>` as usual. If you don't want to install the toolchain into
@@ -117,9 +118,11 @@ options.
```bash
../gcc-<VERSION>/configure \
--prefix=/usr/local/mipsel-none-elf --target=mipsel-none-elf \
- --disable-docs --disable-nls --disable-libada --disable-libssp \
- --disable-libquadmath --disable-libstdc++-v3 --with-float=soft \
- --enable-languages=c,c++ --with-gnu-as --with-gnu-ld
+ --disable-docs --disable-nls --disable-werror --disable-libada \
+ --disable-libssp --disable-libquadmath --disable-threads \
+ --disable-libgomp --disable-libstdcxx-pch --disable-hosted-libstdcxx \
+ --enable-languages=c,c++ --without-isl --without-headers \
+ --with-float=soft --with-gnu-as --with-gnu-ld
```
If you previously set a custom installation path, remember to set it here as
@@ -172,7 +175,7 @@ that runs on Windows.
../binutils-<VERSION>/configure \
--build=x86_64-linux-gnu --host=x86_64-w64-mingw32 \
--prefix=/tmp/mipsel-none-elf --target=mipsel-none-elf \
- --disable-docs --disable-nls --with-float=soft
+ --disable-docs --disable-nls --disable-werror --with-float=soft
```
Then build binutils again:
@@ -187,10 +190,12 @@ that runs on Windows.
```bash
../gcc-<VERSION>/configure \
--build=x86_64-linux-gnu --host=x86_64-w64-mingw32 \
- --prefix=/tmp/mipsel-none-elf --target=mipsel-none-elf \
- --disable-docs --disable-nls --disable-libada --disable-libssp \
- --disable-libquadmath --disable-libstdc++-v3 --with-float=soft \
- --enable-languages=c,c++ --with-gnu-as --with-gnu-ld
+ --prefix=/usr/local/mipsel-none-elf --target=mipsel-none-elf \
+ --disable-docs --disable-nls --disable-werror --disable-libada \
+ --disable-libssp --disable-libquadmath --disable-threads \
+ --disable-libgomp --disable-libstdcxx-pch --disable-hosted-libstdcxx \
+ --enable-languages=c,c++ --without-isl --without-headers \
+ --with-float=soft --with-gnu-as --with-gnu-ld
```
And build it as usual:
@@ -211,14 +216,17 @@ that runs on Windows.
## Note regarding C++ support
-C++ support in PSn00bSDK, besides compile-time features like `constexpr`, only
-goes as far as basic classes, namespaces and the ability to dynamically create
-and delete class objects at any point of the program. The required dependencies
-(which are just wrappers around `malloc()` and `free()`) are supplied by `libc`.
+C++ support in PSn00bSDK is limited to the freestanding subset of the standard
+library provided by GCC, which includes most metaprogramming and compile-time
+utilities but not higher level functionality that requires runtime support such
+as exceptions, containers or streams. Basic C++ features that only depend on the
+compiler (classes, templates, `constexpr` and so on) are fully supported.
-Standard C++ libraries are not implemented and likely never going to be
-implemented due to bloat concerns that it may introduce. Besides, the official
-SDK lacks full C++ support as well.
+Implementing a full STL, while technically possible, is currently out of the
+scope of PSn00bSDK. There are other PS1 SDKs that provide an STL, such as
+[psyqo](https://github.com/grumpycoders/pcsx-redux/tree/main/src/mips/psyqo),
+and they might be a better fit for your project if you plan to make heavy use of
+C++ features.
-----------------------------------------
-_Last updated on 2021-11-23 by spicyjpeg_
+_Last updated on 2023-04-05 by spicyjpeg_