From 4a9987558281c4ac4b235f7965ff323e5dba5673 Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Sun, 27 Mar 2022 16:26:50 +0200 Subject: [PATCH] LibGL+LibGPU+LibSoftGPU: Add virtual base class for Images This introduces a new device independent base class for Images in LibGPU that also keeps track of the device from which it was created in order to prevent assigning images across devices. --- Userland/Libraries/LibGL/Tex/Texture.h | 8 +++--- Userland/Libraries/LibGPU/Image.h | 35 +++++++++++++++++++++++ Userland/Libraries/LibGPU/SamplerConfig.h | 4 +-- Userland/Libraries/LibSoftGPU/Device.cpp | 6 ++-- Userland/Libraries/LibSoftGPU/Device.h | 4 +-- Userland/Libraries/LibSoftGPU/Image.cpp | 23 +++++++++------ Userland/Libraries/LibSoftGPU/Image.h | 11 +++---- Userland/Libraries/LibSoftGPU/Sampler.cpp | 4 +-- 8 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 Userland/Libraries/LibGPU/Image.h diff --git a/Userland/Libraries/LibGL/Tex/Texture.h b/Userland/Libraries/LibGL/Tex/Texture.h index 1009d15028..452201f7d9 100644 --- a/Userland/Libraries/LibGL/Tex/Texture.h +++ b/Userland/Libraries/LibGL/Tex/Texture.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include namespace GL { @@ -21,11 +21,11 @@ public: virtual bool is_texture_3d() const { return false; } virtual bool is_cube_map() const { return false; } - RefPtr device_image() { return m_device_image; } - void set_device_image(RefPtr image) { m_device_image = image; } + RefPtr device_image() { return m_device_image; } + void set_device_image(RefPtr image) { m_device_image = image; } private: - RefPtr m_device_image; + RefPtr m_device_image; }; } diff --git a/Userland/Libraries/LibGPU/Image.h b/Userland/Libraries/LibGPU/Image.h new file mode 100644 index 0000000000..4803d4ec17 --- /dev/null +++ b/Userland/Libraries/LibGPU/Image.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Stephan Unverwerth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace GPU { + +class Image : public RefCounted { +public: + Image(void const* ownership_token) + : m_ownership_token { ownership_token } + { + } + + virtual ~Image() { } + + virtual void write_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void const* data, ImageDataLayout const& layout) = 0; + virtual void read_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void* data, ImageDataLayout const& layout) const = 0; + virtual void copy_texels(Image const& source, unsigned source_layer, unsigned source_level, Vector3 const& source_offset, Vector3 const& size, unsigned destination_layer, unsigned destination_level, Vector3 const& destination_offset) = 0; + + void const* ownership_token() const { return m_ownership_token; } + bool has_same_ownership_token(Image const& other) const { return other.ownership_token() == ownership_token(); } + +private: + void const* const m_ownership_token { nullptr }; +}; + +} diff --git a/Userland/Libraries/LibGPU/SamplerConfig.h b/Userland/Libraries/LibGPU/SamplerConfig.h index fe121913ab..42ccdd2c76 100644 --- a/Userland/Libraries/LibGPU/SamplerConfig.h +++ b/Userland/Libraries/LibGPU/SamplerConfig.h @@ -6,8 +6,8 @@ #pragma once +#include #include -#include namespace GPU { @@ -37,7 +37,7 @@ enum class TextureEnvMode { }; struct SamplerConfig final { - RefPtr bound_image; + RefPtr bound_image; MipMapFilter mipmap_filter { MipMapFilter::Nearest }; TextureFilter texture_mag_filter { TextureFilter::Linear }; TextureFilter texture_min_filter { TextureFilter::Linear }; diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index 62f615206d..ad721f2ee4 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -1219,7 +1219,7 @@ GPU::DepthType Device::get_depthbuffer_value(int x, int y) return m_frame_buffer->depth_buffer()->scanline(y)[x]; } -NonnullRefPtr Device::create_image(GPU::ImageFormat format, unsigned width, unsigned height, unsigned depth, unsigned levels, unsigned layers) +NonnullRefPtr Device::create_image(GPU::ImageFormat format, unsigned width, unsigned height, unsigned depth, unsigned levels, unsigned layers) { VERIFY(format == GPU::ImageFormat::BGRA8888); VERIFY(width > 0); @@ -1228,11 +1228,13 @@ NonnullRefPtr Device::create_image(GPU::ImageFormat format, unsigned widt VERIFY(levels > 0); VERIFY(layers > 0); - return adopt_ref(*new Image(width, height, depth, levels, layers)); + return adopt_ref(*new Image(this, width, height, depth, levels, layers)); } void Device::set_sampler_config(unsigned sampler, GPU::SamplerConfig const& config) { + VERIFY(config.bound_image.is_null() || config.bound_image->ownership_token() == this); + m_samplers[sampler].set_config(config); } diff --git a/Userland/Libraries/LibSoftGPU/Device.h b/Userland/Libraries/LibSoftGPU/Device.h index 14955542d7..2816e947da 100644 --- a/Userland/Libraries/LibSoftGPU/Device.h +++ b/Userland/Libraries/LibSoftGPU/Device.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,6 @@ #include #include #include -#include #include #include @@ -62,7 +62,7 @@ public: GPU::ColorType get_color_buffer_pixel(int x, int y); GPU::DepthType get_depthbuffer_value(int x, int y); - NonnullRefPtr create_image(GPU::ImageFormat format, unsigned width, unsigned height, unsigned depth, unsigned levels, unsigned layers); + NonnullRefPtr create_image(GPU::ImageFormat format, unsigned width, unsigned height, unsigned depth, unsigned levels, unsigned layers); void set_sampler_config(unsigned, GPU::SamplerConfig const&); void set_light_state(unsigned, GPU::Light const&); diff --git a/Userland/Libraries/LibSoftGPU/Image.cpp b/Userland/Libraries/LibSoftGPU/Image.cpp index bd7f6217e5..ee986c4cfd 100644 --- a/Userland/Libraries/LibSoftGPU/Image.cpp +++ b/Userland/Libraries/LibSoftGPU/Image.cpp @@ -9,8 +9,9 @@ namespace SoftGPU { -Image::Image(unsigned width, unsigned height, unsigned depth, unsigned max_levels, unsigned layers) - : m_num_layers(layers) +Image::Image(void* const ownership_token, unsigned width, unsigned height, unsigned depth, unsigned max_levels, unsigned layers) + : GPU::Image(ownership_token) + , m_num_layers(layers) , m_mipmap_buffers(FixedArray>>::must_create_but_fixme_should_propagate_errors(layers * max_levels)) { VERIFY(width > 0); @@ -77,13 +78,17 @@ void Image::read_texels(unsigned layer, unsigned level, Vector3 const& } } -void Image::copy_texels(Image const& source, unsigned source_layer, unsigned source_level, Vector3 const& source_offset, Vector3 const& size, unsigned destination_layer, unsigned destination_level, Vector3 const& destination_offset) +void Image::copy_texels(GPU::Image const& source, unsigned source_layer, unsigned source_level, Vector3 const& source_offset, Vector3 const& size, unsigned destination_layer, unsigned destination_level, Vector3 const& destination_offset) { - VERIFY(source_layer < source.num_layers()); - VERIFY(source_level < source.num_levels()); - VERIFY(source_offset.x() + size.x() <= source.level_width(source_level)); - VERIFY(source_offset.y() + size.y() <= source.level_height(source_level)); - VERIFY(source_offset.z() + size.z() <= source.level_depth(source_level)); + VERIFY(source.has_same_ownership_token(*this)); + + auto const& src_image = static_cast(source); + + VERIFY(source_layer < src_image.num_layers()); + VERIFY(source_level < src_image.num_levels()); + VERIFY(source_offset.x() + size.x() <= src_image.level_width(source_level)); + VERIFY(source_offset.y() + size.y() <= src_image.level_height(source_level)); + VERIFY(source_offset.z() + size.z() <= src_image.level_depth(source_level)); VERIFY(destination_layer < num_layers()); VERIFY(destination_level < num_levels()); VERIFY(destination_offset.x() + size.x() <= level_width(destination_level)); @@ -93,7 +98,7 @@ void Image::copy_texels(Image const& source, unsigned source_layer, unsigned sou for (unsigned z = 0; z < size.z(); ++z) { for (unsigned y = 0; y < size.y(); ++y) { for (unsigned x = 0; x < size.x(); ++x) { - auto color = source.texel(source_layer, source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z); + auto color = src_image.texel(source_layer, source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z); set_texel(destination_layer, destination_level, destination_offset.x() + x, destination_offset.y() + y, destination_offset.z() + z, color); } } diff --git a/Userland/Libraries/LibSoftGPU/Image.h b/Userland/Libraries/LibSoftGPU/Image.h index bbfe154138..99c2348bfc 100644 --- a/Userland/Libraries/LibSoftGPU/Image.h +++ b/Userland/Libraries/LibSoftGPU/Image.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -133,9 +134,9 @@ inline static void pack_color(FloatVector4 const& color, void* ptr, GPU::ImageFo } } -class Image final : public RefCounted { +class Image final : public GPU::Image { public: - Image(unsigned width, unsigned height, unsigned depth, unsigned max_levels, unsigned layers); + Image(void* const ownership_token, unsigned width, unsigned height, unsigned depth, unsigned max_levels, unsigned layers); unsigned level_width(unsigned level) const { return m_mipmap_buffers[level]->width(); } unsigned level_height(unsigned level) const { return m_mipmap_buffers[level]->height(); } @@ -156,9 +157,9 @@ public: pack_color(color, texel_pointer(layer, level, x, y, z), GPU::ImageFormat::BGRA8888); } - void write_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void const* data, GPU::ImageDataLayout const& layout); - void read_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void* data, GPU::ImageDataLayout const& layout) const; - void copy_texels(Image const& source, unsigned source_layer, unsigned source_level, Vector3 const& source_offset, Vector3 const& size, unsigned destination_layer, unsigned destination_level, Vector3 const& destination_offset); + virtual void write_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void const* data, GPU::ImageDataLayout const& layout) override; + virtual void read_texels(unsigned layer, unsigned level, Vector3 const& offset, Vector3 const& size, void* data, GPU::ImageDataLayout const& layout) const override; + virtual void copy_texels(GPU::Image const& source, unsigned source_layer, unsigned source_level, Vector3 const& source_offset, Vector3 const& size, unsigned destination_layer, unsigned destination_level, Vector3 const& destination_offset) override; private: void const* texel_pointer(unsigned layer, unsigned level, int x, int y, int z) const diff --git a/Userland/Libraries/LibSoftGPU/Sampler.cpp b/Userland/Libraries/LibSoftGPU/Sampler.cpp index fa37aa6836..082760a4b9 100644 --- a/Userland/Libraries/LibSoftGPU/Sampler.cpp +++ b/Userland/Libraries/LibSoftGPU/Sampler.cpp @@ -109,7 +109,7 @@ Vector4 Sampler::sample_2d(Vector2 const& uv) if (m_config.bound_image.is_null()) return expand4(FloatVector4 { 1, 0, 0, 1 }); - auto const& image = *m_config.bound_image; + auto const& image = *static_ptr_cast(m_config.bound_image); // FIXME: Make base level configurable with glTexParameteri(GL_TEXTURE_BASE_LEVEL, base_level) constexpr unsigned base_level = 0; @@ -152,7 +152,7 @@ Vector4 Sampler::sample_2d(Vector2 const& uv) Vector4 Sampler::sample_2d_lod(Vector2 const& uv, AK::SIMD::u32x4 level, GPU::TextureFilter filter) const { - auto const& image = *m_config.bound_image; + auto const& image = *static_ptr_cast(m_config.bound_image); u32x4 const layer = expand4(0u); u32x4 const width = {