Drawable Renderer (#1570), Texture2D storage allocation fixes, async image transfer

This commit is contained in:
mwilsnd
2023-06-02 15:35:32 -05:00
committed by Bart Louwers
parent 0f321fb11e
commit 2f4be630c2
3 changed files with 74 additions and 23 deletions

View File

@@ -50,6 +50,10 @@ public:
/// @return this
virtual Texture2D& setSize(Size size_) noexcept = 0;
/// @brief Sets the internal image
/// @param image_ Image data to transfer
virtual Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept = 0;
/// @brief Get the size of the texture
/// @return Size of the texture
virtual Size getSize() const noexcept = 0;
@@ -68,6 +72,7 @@ public:
virtual size_t numChannels() const noexcept = 0;
/// @brief Create the texture with default initialized memory.
/// @note Be sure to configure a valid size and format.
virtual void create() noexcept = 0;
/// @brief Upload image data to the texture resource
@@ -93,10 +98,17 @@ public:
uploadSubRegion(&img.data[0], img.size, xOffset, yOffset);
}
/// @brief Upload staged image data if present and required.
/// @see needsUpload
virtual void upload() noexcept = 0;
/// @brief Get the underlying GL texture resource
/// @note: Compat with legacy textures, to be refactored
/// @return gfx::TextureResource
virtual gfx::TextureResource& getResource() = 0;
/// @brief Check whether the texture needs upload
virtual bool needsUpload() const noexcept = 0;
};
} // namespace gfx

View File

@@ -24,6 +24,8 @@ public: // gfx::Texture2D
Texture2D& setSize(Size size_) noexcept override;
Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept override;
Size getSize() const noexcept override { return size; }
size_t getDataSize() const noexcept override;
@@ -36,12 +38,15 @@ public: // gfx::Texture2D
void upload(const void* pixelData, const Size& size_) noexcept override;
void uploadSubRegion(const void* pixelData, const Size& size, uint16_t xOffset, uint16_t yOffset) noexcept override;
void upload() noexcept override;
gfx::TextureResource& getResource() override {
assert(textureResource);
return *textureResource;
}
bool needsUpload() const noexcept override { return !!image; };
public:
/// @brief Get the OpenGL handle ID for the underlying resource
/// @return GLuint
@@ -58,14 +63,19 @@ public:
/// @brief Unbind the texture, if it was bound
void unbind() noexcept;
private:
void createObject() noexcept;
void createStorage(const void* data = nullptr) noexcept;
private:
gl::Context& context;
std::unique_ptr<gfx::TextureResource> textureResource{nullptr};
SamplerState samplerState{};
gfx::TexturePixelType pixelFormat;
gfx::TextureChannelDataType channelType;
gfx::TexturePixelType pixelFormat{gfx::TexturePixelType::RGBA};
gfx::TextureChannelDataType channelType{gfx::TextureChannelDataType::UnsignedByte};
std::shared_ptr<PremultipliedImage> image{nullptr};
Size size{0, 0};
bool samplerStateDirty{false};

View File

@@ -38,6 +38,11 @@ Texture2D& Texture2D::setSize(mbgl::Size size_) noexcept {
return *this;
}
Texture2D& Texture2D::setImage(std::shared_ptr<PremultipliedImage> image_) noexcept {
image = std::move(image_);
return *this;
}
size_t Texture2D::getDataSize() const noexcept {
return size.width * size.height * getPixelStride();
}
@@ -64,9 +69,9 @@ size_t Texture2D::numChannels() const noexcept {
}
}
void Texture2D::create() noexcept {
void Texture2D::createObject() noexcept {
// Create a new texture object
assert(!textureResource);
auto obj = context.createUniqueTexture();
const auto storageSize = gl::TextureResource::getStorageSize(size, pixelFormat, channelType);
context.renderingStats().memTextures += storageSize;
@@ -75,6 +80,32 @@ void Texture2D::create() noexcept {
textureResource = std::make_unique<gl::TextureResource>(std::move(obj), storageSize);
}
void Texture2D::createStorage(const void* data) noexcept {
assert(textureResource);
// Create backing storage for our texture object
using namespace platform;
// Bind to TU 0 and upload
context.activeTextureUnit = 0;
context.texture[0] = getTextureID();
updateSamplerConfiguration();
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D,
0,
Enum<gfx::TexturePixelType>::to(pixelFormat),
size.width,
size.height,
0,
Enum<gfx::TexturePixelType>::to(pixelFormat),
Enum<gfx::TextureChannelDataType>::to(channelType),
data));
}
void Texture2D::create() noexcept {
createObject();
createStorage();
}
platform::GLuint Texture2D::getTextureID() const noexcept {
return static_cast<gl::TextureResource&>(*textureResource).texture;
}
@@ -139,28 +170,18 @@ void Texture2D::unbind() noexcept {
void Texture2D::upload(const void* pixelData, const Size& size_) noexcept {
using namespace platform;
if (!textureResource) {
create();
}
assert(textureResource);
// Bind to TU 0 and upload
context.activeTextureUnit = 0;
context.texture[0] = getTextureID();
updateSamplerConfiguration();
if (!textureResource || size_ == Size{0, 0} || size_ != size) {
// Create the texture object if we don't already have one
if (!textureResource) {
createObject();
}
if (size_ == Size{0, 0} || size_ != size) {
size = size_;
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D,
0,
Enum<gfx::TexturePixelType>::to(pixelFormat),
size.width,
size.height,
0,
Enum<gfx::TexturePixelType>::to(pixelFormat),
Enum<gfx::TextureChannelDataType>::to(channelType),
pixelData));
createStorage(pixelData);
} else {
// Upload to existing memory
uploadSubRegion(pixelData, size, 0, 0);
}
}
@@ -174,7 +195,6 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
// Bind to TU 0 and upload
context.activeTextureUnit = 0;
context.texture[0] = getTextureID();
MBGL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D,
0,
xOffset,
@@ -186,5 +206,14 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
pixelData));
}
void Texture2D::upload() noexcept {
if (image && image->valid()) {
setFormat(gfx::TexturePixelType::RGBA,
gfx::TextureChannelDataType::UnsignedByte);
upload(&(*image).data[0], image->size);
image.reset();
}
}
} // namespace gl
} // namespace mbgl