From bb28492af07ddf0dce3cd6d6595232d9473d8973 Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Sat, 17 Sep 2022 17:16:31 +0200 Subject: 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. --- Userland/Libraries/LibSoftGPU/Config.h | 7 +++++++ Userland/Libraries/LibSoftGPU/Device.cpp | 22 +++++++++++++--------- Userland/Libraries/LibSoftGPU/PixelQuad.h | 21 ++++++++++++++++++++- 3 files changed, 40 insertions(+), 10 deletions(-) (limited to 'Userland/Libraries/LibSoftGPU') diff --git a/Userland/Libraries/LibSoftGPU/Config.h b/Userland/Libraries/LibSoftGPU/Config.h index a8b6d1fca3..72ea23c154 100644 --- a/Userland/Libraries/LibSoftGPU/Config.h +++ b/Userland/Libraries/LibSoftGPU/Config.h @@ -32,6 +32,13 @@ static_assert(NUM_SHADER_INPUTS >= 4 + GPU::NUM_TEXTURE_UNITS * 4); static constexpr int SHADER_INPUT_VERTEX_COLOR = 0; static constexpr int SHADER_INPUT_FIRST_TEXCOORD = 4; +static constexpr int NUM_SHADER_OUTPUTS = 4; + +// Verify that we have enough outputs to hold the fragment's color +static_assert(NUM_SHADER_OUTPUTS >= 4); + +static constexpr int SHADER_OUTPUT_FIRST_COLOR = 0; + // See: https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_edge_color_problem // FIXME: make this dynamically configurable through ConfigServer static constexpr bool CLAMP_DEPRECATED_BEHAVIOR = false; diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index 98b5ef26e5..e971ad01a7 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -186,7 +186,7 @@ void Device::setup_blend_factors() ALWAYS_INLINE static void test_alpha(PixelQuad& quad, GPU::AlphaTestFunction alpha_test_function, f32x4 const& reference_value) { - auto const alpha = quad.out_color.w(); + auto const alpha = quad.get_output_float(SHADER_OUTPUT_FIRST_COLOR + 3); switch (alpha_test_function) { case GPU::AlphaTestFunction::Always: @@ -494,11 +494,13 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera if (m_options.enable_blending || m_options.color_mask != 0xffffffff) dst_u32 = load4_masked(color_ptrs[0], color_ptrs[1], color_ptrs[2], color_ptrs[3], quad.mask); + auto out_color = quad.get_output_vector4(SHADER_OUTPUT_FIRST_COLOR); + if (m_options.enable_blending) { INCREASE_STATISTICS_COUNTER(g_num_pixels_blended, maskcount(quad.mask)); // Blend color values from pixel_staging into color_buffer - auto const& src = quad.out_color; + auto const& src = out_color; auto dst = to_vec4(dst_u32); auto src_factor = expand4(m_alpha_blend_factors.src_constant) @@ -513,10 +515,10 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera + dst * m_alpha_blend_factors.dst_factor_dst_color + Vector4 { dst.w(), dst.w(), dst.w(), dst.w() } * m_alpha_blend_factors.dst_factor_dst_alpha; - quad.out_color = src * src_factor + dst * dst_factor; + out_color = src * src_factor + dst * dst_factor; } - auto const argb32_color = to_argb32(quad.out_color); + auto const argb32_color = to_argb32(out_color); if (m_options.color_mask == 0xffffffff) store4_masked(argb32_color, color_ptrs[0], color_ptrs[1], color_ptrs[2], color_ptrs[3], quad.mask); else @@ -1331,7 +1333,6 @@ ALWAYS_INLINE void Device::shade_fragments(PixelQuad& quad) break; } } - quad.out_color = current_color; // Calculate fog // Math from here: https://opengl-notes.readthedocs.io/en/latest/topics/texturing/aliasing.html @@ -1358,13 +1359,16 @@ ALWAYS_INLINE void Device::shade_fragments(PixelQuad& quad) // Mix texel's RGB with fog's RBG - leave alpha alone auto fog_color = expand4(m_options.fog_color); - quad.out_color.set_x(mix(fog_color.x(), quad.out_color.x(), factor)); - quad.out_color.set_y(mix(fog_color.y(), quad.out_color.y(), factor)); - quad.out_color.set_z(mix(fog_color.z(), quad.out_color.z(), factor)); + current_color.set_x(mix(fog_color.x(), current_color.x(), factor)); + current_color.set_y(mix(fog_color.y(), current_color.y(), factor)); + current_color.set_z(mix(fog_color.z(), current_color.z(), factor)); } + quad.set_output(SHADER_OUTPUT_FIRST_COLOR, current_color.x()); + quad.set_output(SHADER_OUTPUT_FIRST_COLOR + 1, current_color.y()); + quad.set_output(SHADER_OUTPUT_FIRST_COLOR + 2, current_color.z()); // Multiply coverage with the fragment's alpha to obtain the final alpha value - quad.out_color.set_w(quad.out_color.w() * quad.coverage); + quad.set_output(SHADER_OUTPUT_FIRST_COLOR + 3, current_color.w() * quad.coverage); } void Device::resize(Gfx::IntSize size) diff --git a/Userland/Libraries/LibSoftGPU/PixelQuad.h b/Userland/Libraries/LibSoftGPU/PixelQuad.h index 643ea4a07e..d318093844 100644 --- a/Userland/Libraries/LibSoftGPU/PixelQuad.h +++ b/Userland/Libraries/LibSoftGPU/PixelQuad.h @@ -40,11 +40,30 @@ struct PixelQuad final { inputs[index + 3]); } + void set_output(int index, f32x4 value) { outputs[index] = value; } + f32x4 get_output_float(int index) const { return outputs[index]; } + + void set_output(int index, Vector4 const& value) + { + outputs[index] = value.x(); + outputs[index + 1] = value.y(); + outputs[index + 2] = value.z(); + outputs[index + 3] = value.w(); + } + Vector4 get_output_vector4(int index) const + { + return Vector4( + outputs[index], + outputs[index + 1], + outputs[index + 2], + outputs[index + 3]); + } + Vector2 screen_coordinates; Vector3 barycentrics; f32x4 depth; Array inputs; - Vector4 out_color; + Array outputs; f32x4 fog_depth; i32x4 mask; f32x4 coverage { expand4(1.f) }; -- cgit v1.2.3