Commit Graph

153 Commits

Author SHA1 Message Date
Jelle Raaijmakers
403d3bbdaf LibSoftGPU: Optimize GPU::Vertex lists
On my machine, benchmarking 3DFileViewer revealed ~2.5% of CPU time
spent in `Vector<GPU::Vertex>::try_append`. By carefully managing list
capacities, we can remove this method from profiles altogether.
2023-10-15 12:14:07 +02:00
Jelle Raaijmakers
edcb6176ce LibGL+Lib*GPU: Set model view and projection matrices separately
LibSoftGPU used to calculate the normal transformation based on the
model view transformation for every primitive, because that's when we
sent over the matrix. By making LibGL a bit smarter and only update the
matrices when they could have changed, we only need to calculate the
normal transformation once on every matrix update.

When viewing `Tuba.obj` in 3DFileViewer, this brings the percentage of
time spent in `FloatMatrix4x4::inverse()` down from 15% to 0%. :^)
2023-10-15 12:14:07 +02:00
Bastiaan van der Plaat
494a8cb816 AK: Add to_radians and to_degrees math functions 2023-09-10 08:38:29 +01:00
Jelle Raaijmakers
f391ccfe53 LibGfx+Everywhere: Change Gfx::Rect to be endpoint exclusive
Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.

This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.

All users of `Gfx::Rect` have been updated accordingly.
2023-05-23 12:35:42 +02:00
Jelle Raaijmakers
62285e0569 LibSoftGPU: Use multiplication instead of division for linear fog
Sampling profiling shows a reduction of nearly 60% for the linear fog
calculation case.
2023-02-18 01:45:00 +01:00
Jelle Raaijmakers
f54d9c0a61 LibSoftGPU: Use AK::SIMD::exp_approximate instead of ::exp
The approximate version is properly vectorized and results in fewer
stalls than the `::exp` version.
2023-02-18 01:45:00 +01:00
Jelle Raaijmakers
62f4486190 LibSoftGPU: Only enable texture stages if required
Copying over every texel (4x`f32x4`) for every texture unit is
relatively expensive. By checking if we even need to remember these
texel values, we reduce the time spent in `rasterize_triangle` by
around 2% as measured in Quake III.
2023-02-02 14:38:26 +01:00
Jelle Raaijmakers
69b94e4235 LibSoftGPU: Make blending simpler and more efficient
Previously, we would precalculate "alpha blend factors" on every
configuration update and then calculate the source and destination
blending factors in one go using all these factors. The idea here was
probably that we would get better performance by avoiding branching.

However, by measuring blending performance in Quake III, it seems that
this simpler version that only calculates the required factors reduces
the CPU time spent in `rasterize_triangle` by 3%.

As a bonus, `GL_SRC_ALPHA_SATURATE` is now also implemented.
2023-02-02 14:38:26 +01:00
Jelle Raaijmakers
5c1038e54f LibSoftGPU: Remove DeprecatedString usage 2023-01-30 13:49:52 -05:00
Jelle Raaijmakers
44d679ba7e LibSoftGPU: Remove workaround for i686 depth comparison 2023-01-09 12:55:41 +01:00
Andrew Kaster
a492e2018d Userland: Silence warnings from ElapsedTimer::elapsed() type change
We changed elapsed() to return i64 instead of int as that's what
AK::Time::to_milliseconds() returns, causing a bunch of implicit lossy
conversions in callers. Clean those up with a mix of type changes and
casts.
2023-01-07 14:51:04 +01:00
Stephan Unverwerth
c25359df47 LibSoftGPU: Delegate shader creation to new class ShaderCompiler 2022-12-17 22:39:09 -07:00
Stephan Unverwerth
b18bf702ea LibSoftGPU: Implement shader processor for SoftGPU ISA
This adds a shader processor that executes our ISA when a fragment
shader is currently bound to the device.
2022-12-17 22:39:09 -07:00
Stephan Unverwerth
1e548a84d6 LibSoftGPU: Define a simple shader instruction set
This adds a simple instruction set with basic operations and adds an
instruction list to the shader class.
2022-12-17 22:39:09 -07:00
Stephan Unverwerth
bb28492af0 LibSoftGPU: Make output in PixelQuad generic
Same as with inputs, we define outputs as a generic array of floats.
This can later be expanded to accomodate multiple render targets or
vertex attributes in the case of a vertex shader.
2022-12-17 22:39:09 -07:00
Stephan Unverwerth
c008b6ce18 LibSoftGPU: Make input in PixelQuad generic
Previously we would store vertex color and texture coordinates in
separate fields in PixelQuad. To make them accessible from shaders we
need to store them as a completely generic array of floats.
2022-12-17 22:39:09 -07:00
Stephan Unverwerth
49139d5f4e LibSoftGPU: Allow binding a fragment shader 2022-12-17 22:39:09 -07:00
Stephan Unverwerth
93ab2db80f LibGL+LibSoftGPU: Add GPU side shader infrastructure
This adds a shader class to LibSoftGPU and makes use of it when linking
GLSL program in LibGL. Also adds actual rendering code to the shader
tests.
2022-12-17 22:39:09 -07:00
MacDue
27fae78335 Meta+Userland: Pass Gfx::IntSize by value
Just two ints like Gfx::IntPoint.
2022-12-07 11:48:27 +01:00
Linus Groh
57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Jelle Raaijmakers
88ca72aa79 LibSoftGPU: Extract argb32_color value in rasterization
This makes it easier to correlate slow instructions in the disassembly
view of ProfileViewer.
2022-10-19 22:22:58 +02:00
Jelle Raaijmakers
681695a07a LibSoftGPU: Make alpha testing a static function
There is no need to access the Device's members for alpha testing; pass
in the required alpha function and reference value.
2022-10-19 22:22:58 +02:00
Jelle Raaijmakers
4e63ce231f LibSoftGPU: Clean up Sampler imports 2022-10-19 22:22:58 +02:00
cflip
abc0c44f0b LibGL+LibGPU+LibSoftGPU: Report maximum texture size 2022-10-19 22:07:05 +02:00
Jelle Raaijmakers
1aa1c89afa LibGL+LibGPU+LibSoftGPU: Report texture clamp to edge support 2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
087f565700 LibSoftGPU: Divide texture coordinates by Q
Up until now, we have only dealt with games that pass Q = 1 for their
texture coordinates. PrBoom+, however, relies on proper homogenous
texture coordinates for its relatively complex sky rendering, which
means that we should perform this per-fragment division.
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
00d46e5d77 LibGL+LibGPU+LibSoftGPU: Implement matrix stack per texture unit
Each texture unit now has its own texture transformation matrix stack.
Introduce a new texture unit configuration that is synced when changed.
Because we're no longer passing a silly `Vector` when drawing each
primitive, this results in a slightly improved frames per second :^)
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
dda5987684 LibGL+LibGPU+LibSoftGPU: Remove concept of layer in favor of depth
Looking at how Khronos defines layers:

  https://www.khronos.org/opengl/wiki/Array_Texture

We both have 3D textures and layers of 2D textures, which can both be
encoded in our existing `Typed3DBuffer` as depth. Since we support
depth already in the GPU API, remove layer everywhere.

Also pass in `Texture2D::LOG2_MAX_TEXTURE_SIZE` as the maximum number
of mipmap levels, so we do not allocate 999 levels on each Image
instantiation.
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
44953a4301 LibGL+LibGPU+LibSoftGPU: Implement glCopyTex(Sub)?Image2d
These two methods copy from the frame buffer to (part of) a texture.
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
eb81b66b4e LibGL+LibGPU+LibSoftGPU: Rename blit_color_buffer_to
This makes it consistent with our other `blit_from_color_buffer` and
paves the way for a third method that will be introduced in one of the
next commits.
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
1d36bfdac1 LibGL+LibSoftGPU: Implement fixed pipeline support for GL_COMBINE
`GL_COMBINE` is basically a fixed function calculator to perform simple
arithmetics on configurable fragment sources. This patch implements a
number of texture env parameters with support for the RGBA internal
format.
2022-09-11 22:37:07 +01:00
Jelle Raaijmakers
b42feb76a0 LibSoftGPU: Use approximation for maximum depth slope
OpenGL allows GPUs to approximate a triangle's maximum depth slope
which prevents a number computationally expensive instructions. On my
machine, this gives me +6% FPS in Quake III.

We are able to reuse `render_bounds` here since it is the containing
rect of the (X, Y) window coordinates of the triangle, thus its width
and height are the maximum delta X and delta Y, respectively.
2022-09-08 12:07:03 -04:00
Jelle Raaijmakers
94f016b363 LibGL+LibGPU+LibSoftGPU: Report texture env add extension
The Quake 3 port makes use of this extension to determine a more
efficient multitexturing strategy. Since LibSoftGPU supports it, let's
report the extension in LibGL. :^)
2022-08-28 23:45:43 +01:00
Jelle Raaijmakers
84c4b66721 LibGL+LibGPU+LibSoftGPU: Implement texture pixel format support
In OpenGL this is called the (base) internal format which is an
expectation expressed by the client for the minimum supported texel
storage format in the GPU for textures.

Since we store everything as RGBA in a `FloatVector4`, the only thing
we do in this patch is remember the expected internal format, and when
we write new texels we fixate the value for the alpha channel to 1 for
two formats that require it.

`PixelConverter` has learned how to transform pixels during transfer to
support this.
2022-08-27 12:28:05 +02:00
Jelle Raaijmakers
eb7c3d16fb LibGL+LibGPU+LibSoftGPU: Implement flexible pixel format conversion
A GPU (driver) is now responsible for reading and writing pixels from
and to user data. The client (LibGL) is responsible for specifying how
the user data must be interpreted or written to.

This allows us to centralize all pixel format conversion in one class,
`LibSoftGPU::PixelConverter`. For both the input and output image, it
takes a specification containing the image dimensions, the pixel type
and the selection (basically a clipping rect), and converts the pixels
from the input image to the output image.

Effectively this means we now support almost all OpenGL 1.5 formats,
and all custom logic has disappeared from:
  - `glDrawPixels`
  - `glReadPixels`
  - `glTexImage2D`
  - `glTexSubImage2D`

The new logic is still unoptimized, but on my machine I experienced no
noticeable slowdown. :^)
2022-08-27 12:28:05 +02:00
Linus Groh
173dcfb7cb Everywhere: Fix a bunch of typos 2022-05-29 15:22:00 +02:00
Jelle Raaijmakers
421a80bf43 LibSoftGPU: Update coverage bits after alpha testing
Also skip the test for the `::Always` alpha test function in the hot
loop. This test function is very unlikely to be set, so leave that up
to `::test_alpha()`.
2022-05-15 12:15:12 +02:00
Jelle Raaijmakers
1a338844fa LibSoftGPU: Make Device statistics i64 again
They were erroneously converted into `u64` by me in a previous commit,
causing the overdraw statistic to go haywire.
2022-05-15 12:15:12 +02:00
RKBethke
0836912a6d LibGL+LibGPU+LibSoftGPU: Implement and expose glClipPlane
This commit implements glClipPlane and its supporting calls, backed
by new support for user-defined clip planes in the software GPU clipper.

This fixes some visual bugs seen in the Quake III port, in which mirrors
would only reflect correctly from close distances.
2022-05-11 23:09:47 +02:00
Jelle Raaijmakers
5861f1821e LibSoftGPU: Clamp polygon depth values to 0.f - 1.f
According to the OpenGL spec, we're expected to clamp the fragment
depth values to the range `0.f - 1.f` for all polygons.

This fixes Z-fighting issues with the sky in Quake 3.
2022-05-11 20:25:17 +02:00
Jelle Raaijmakers
b8c0ebccfd LibSoftGPU: Implement depth offset factor
This implements the depth offset factor that you can set through e.g.
OpenGL's `glPolygonOffset`. Without it, triangles might start to Z-
fight amongst each other.

This fixes the floor decals in Quake 3.
2022-05-10 19:36:41 +02:00
Jelle Raaijmakers
a20bf80b05 LibGL+LibGPU+LibSoftGPU: Implement point and line drawing
Implement (anti)aliased point drawing and anti-aliased line drawing.
Supported through LibGL's `GL_POINTS`, `GL_LINES`, `GL_LINE_LOOP` and
`GL_LINE_STRIP`.

In order to support this, `LibSoftGPU`s rasterization logic was
reworked. Now, any primitive can be drawn by invoking `rasterize()`
which takes care of the quad loop and fragment testing logic. Three
callbacks need to be passed:

* `set_coverage_mask`: the primitive needs to provide initial coverage
   mask information so fragments can be discarded early.
* `set_quad_depth`: fragments survived stencil testing, so depth values
  need to be set so depth testing can take place.
* `set_quad_attributes`: fragments survived depth testing, so fragment
  shading is going to take place. All attributes like color, tex coords
  and fog depth need to be set so alpha testing and eventually,
  fragment rasterization can take place.

As of this commit, there are four instantiations of this function:

* Triangle rasterization
* Points - aliased
* Points - anti-aliased
* Lines - anti-aliased

In order to standardize vertex processing for all primitive types,
things like vertex transformation, lighting and tex coord generation
are now taking place before clipping.
2022-05-09 21:49:48 +02:00
Jelle Raaijmakers
950ded7ab9 LibSoftGPU: Mention correct i686 target in Device comment 2022-05-09 21:49:48 +02:00
Jelle Raaijmakers
7906ada015 LibSoftGPU: Update coverage mask bits during rasterization
We were not updating `coverage_bits` causing us to perform just a
little bit more work than strictly necessary.
2022-05-09 21:49:48 +02:00
Hendiadyoin1
d866637074 LibSoftGPU: Use round_to<int> in Device::get_rasterization_rect_of_size 2022-05-07 20:25:39 +02:00
Jelle Raaijmakers
a699e0a9d7 LibSoftGPU: Remove initial fog factor value from Device
This value was always overwritten. No functional changes.
2022-05-05 20:50:46 +02:00
Jelle Raaijmakers
526390ec06 LibSoftGPU: Move back to i32-based subpixels
Our move to floating point precision has eradicated the pixel artifacts
in Quake 1, but introduced new and not so subtle rendering glitches in
games like Tux Racer. This commit changes three things to get the best
of both worlds:

1. Subpixel logic based on `i32` types was reintroduced, the number of
   bits is set to 6. This reintroduces the artifacts in Quake 1 but
   fixes rendering of Tux Racer.

2. Before triangle culling, subpixel coordinates are calculated and
   stored in `Triangle`. These coordinates are rounded, which fixes the
   Quake 1 artifacts. Tux Racer is unaffected.

3. The triangle area (actually parallelogram area) is also stored in
   `Triangle` so we don't need to recalculate it later on. In our
   previous subpixel code, there was a subtle disconnect between the
   two calculations (one with and one without subpixel precision) which
   resulted in triangles incorrectly being culled. This fixes some
   remaining Quake 1 artifacts.
2022-05-05 20:50:46 +02:00
Jelle Raaijmakers
e70dc20650 LibSoftGPU: Replace some interpolate() calls with VectorN::dot
The dot product is effectively the same as `interpolate()`, allowing us
to use `VectorN`. No functional changes.
2022-05-05 20:50:46 +02:00
Jelle Raaijmakers
dfb218f6a8 LibSoftGPU: East-const interpolate
No functional changes.
2022-05-05 20:50:46 +02:00