From 5c3a4e2c0dc250f6d556dc8eb40aedaccbf6b46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E9=A3=8E=E9=80=8D=E9=81=A5=E6=B8=B8?= Date: Sat, 22 Aug 2026 23:47:33 +0800 Subject: [PATCH] feat(graphics): add in-place texture pixel updates (updateTexture) --- src/modules/graphics/Graphics.h | 11 +++++++++++ src/modules/graphics/vulkan/Graphics.h | 3 +++ src/modules/graphics/vulkan/GraphicsTexture.cpp | 15 +++++++++++---- src/modules/graphics/webgpu/Graphics.cpp | 10 ++++++++++ src/modules/graphics/webgpu/Graphics.h | 2 ++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 74ede360..5d8014d2 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -327,6 +327,17 @@ public: /** @brief Create texture from ImageData with sampler / mipmap options. */ virtual Texture *newTexture(image::ImageData *data, const TextureCreateInfo &info) = 0; + /** + * @brief Replace an existing texture's pixels in place (pointer stays stable). + * + * The new size must match the texture's current dimensions (mip chain and + * sampler are kept); callers that need a different size should create a new + * texture instead. Returns false when the texture is not owned by this + * backend or the backend does not support in-place updates. + */ + virtual bool updateTexture(Texture *texture, int width, int height, + const uint8_t *rgba) = 0; + /** * @brief Recreate the sampler for an existing texture (keeps image / mip chain). * No-op when texture is null or not owned by this Graphics. diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 6bb0b7de..2a70f6f3 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -303,7 +303,10 @@ public: Texture *newTextureFromFile(const std::string &filename) override; bool reloadTextureFromFile(const std::string &filename) override; bool releaseTexture(Texture *texture) override; + bool updateTexture(Texture *texture, int width, int height, + const uint8_t *rgba) override; bool replaceTexturePixels(Texture *tex, image::ImageData *data); + bool replaceTexturePixelsRGBA(Texture *tex, int w, int h, const uint8_t *rgba); void drawTexturedRect(Texture *texture, float x, float y, float w, float h, const Color &color) override; void drawTexturedRectShader(Texture *texture, Shader *shader, float x, float y, float w, float h, const Color &color) override; diff --git a/src/modules/graphics/vulkan/GraphicsTexture.cpp b/src/modules/graphics/vulkan/GraphicsTexture.cpp index 8deb92c3..4371b7f3 100644 --- a/src/modules/graphics/vulkan/GraphicsTexture.cpp +++ b/src/modules/graphics/vulkan/GraphicsTexture.cpp @@ -225,10 +225,17 @@ bool Graphics::releaseTexture(Texture *texture) { bool Graphics::replaceTexturePixels(Texture *tex, image::ImageData *data) { if (!tex || !data) return false; if (data->getFormat() != "RGBA8") return false; - const int w = data->getWidth(); - const int h = data->getHeight(); - const auto *rgba = static_cast(data->getData()); - if (w <= 0 || h <= 0 || !rgba) return false; + return replaceTexturePixelsRGBA(tex, data->getWidth(), data->getHeight(), + static_cast(data->getData())); +} + +bool Graphics::updateTexture(Texture *tex, int width, int height, const uint8_t *rgba) { + if (!tex || width <= 0 || height <= 0 || !rgba) return false; + return replaceTexturePixelsRGBA(tex, width, height, rgba); +} + +bool Graphics::replaceTexturePixelsRGBA(Texture *tex, int w, int h, const uint8_t *rgba) { + if (!tex || !rgba || w <= 0 || h <= 0 || !initialized) return false; TextureCreateInfo info; info.sampler = tex->sampler; diff --git a/src/modules/graphics/webgpu/Graphics.cpp b/src/modules/graphics/webgpu/Graphics.cpp index 54b8083e..e44bd779 100644 --- a/src/modules/graphics/webgpu/Graphics.cpp +++ b/src/modules/graphics/webgpu/Graphics.cpp @@ -1812,6 +1812,16 @@ bool Graphics::releaseTexture(Texture *texture) { return true; } +bool Graphics::updateTexture(Texture *texture, int width, int height, + const uint8_t *rgba) { + // WebGPU backend keeps texture images immutable; rebuild via newTexture. + (void)texture; + (void)width; + (void)height; + (void)rgba; + return false; +} + GpuTexture *Graphics::gpuForTexture(Texture *t) const { return t ? static_cast(t->gpuHandle) : nullptr; } diff --git a/src/modules/graphics/webgpu/Graphics.h b/src/modules/graphics/webgpu/Graphics.h index 3484c0bb..860d9ada 100644 --- a/src/modules/graphics/webgpu/Graphics.h +++ b/src/modules/graphics/webgpu/Graphics.h @@ -161,6 +161,8 @@ public: Texture *newTextureFromFile(const std::string &filename) override; bool reloadTextureFromFile(const std::string &filename) override; bool releaseTexture(Texture *texture) override; + bool updateTexture(Texture *texture, int width, int height, + const uint8_t *rgba) override; void drawTexturedRect(Texture *texture, float x, float y, float w, float h, const Color &color) override;