mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
glTexBufferRange, glTextureBuffer and glTextureBufferRange were all stubs, so a buffer texture could only ever be attached through glTexBuffer -- by binding, and always to the whole buffer. Give the buffer texture the window it is supposed to address. The non-range forms record it as offset 0 with a whole-buffer sentinel rather than the size the buffer happens to have, so a later respecify keeps being followed instead of freezing the texture at yesterday's size. All four entry points now share one attach path, differing only in how they name the texture: by binding for the target forms, by name for the DSA ones. Both backends honour the window: DirectVulkan offsets and clamps the buffer view, DirectGLES uses glTexBufferRange when the texture names a sub-range and keeps plain glTexBuffer for the whole-buffer case, which also works on a driver without the range entry point. GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT reported 0 with a comment explaining that the range entry points were stubbed. It now reports what the device actually requires -- minTexelBufferOffsetAlignment on Vulkan, the driver's own value on GLES -- and the range entry points enforce it. Zero was never a legal answer; the minimum is 1, and an application that trusted it would have built unaligned offsets.
54 lines
2.8 KiB
C++
54 lines
2.8 KiB
C++
// MobileGL - MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include "TextureObject.h"
|
|
#include <MG_State/GLState/BufferState/BufferObject.h>
|
|
|
|
namespace MobileGL {
|
|
namespace MG_State {
|
|
namespace GLState {
|
|
class TextureObjectBuffer : public TextureObjectBase {
|
|
public:
|
|
TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; }
|
|
explicit TextureObjectBuffer(Uint externalIndex);
|
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
|
|
BindingSlot<BufferObject>& GetBufferBindingSlot(
|
|
TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
|
|
|
|
// The window of the attached buffer the texture addresses. glTexBuffer attaches
|
|
// the whole buffer, which is expressed here as an offset of 0 and a size of
|
|
// kWholeBuffer so a later respecify of the buffer keeps being followed - a stored
|
|
// size would freeze the texture at the size the buffer happened to have.
|
|
static constexpr SizeT kWholeBuffer = ~static_cast<SizeT>(0);
|
|
void SetBufferRange(SizeT offset, SizeT size) {
|
|
m_bufferRangeOffset = offset;
|
|
m_bufferRangeSize = size;
|
|
}
|
|
SizeT GetBufferRangeOffset() const { return m_bufferRangeOffset; }
|
|
// Resolved against the buffer's current size, so kWholeBuffer tracks it.
|
|
SizeT GetBufferRangeSizeInBytes() const {
|
|
const auto& buffer = m_bufferBindingSlot.GetBoundObject();
|
|
const SizeT bufferSize = buffer != nullptr ? buffer->GetSize() : 0;
|
|
if (m_bufferRangeSize == kWholeBuffer) return bufferSize;
|
|
const SizeT available = bufferSize > m_bufferRangeOffset ? bufferSize - m_bufferRangeOffset : 0;
|
|
return std::min(m_bufferRangeSize, available);
|
|
}
|
|
|
|
protected:
|
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
|
|
|
BindingSlot<BufferObject> m_bufferBindingSlot = BindingSlot<BufferObject>(BufferTarget::Texture);
|
|
SizeT m_bufferRangeOffset = 0;
|
|
SizeT m_bufferRangeSize = kWholeBuffer;
|
|
const Vector<TextureUploadTarget> m_uploadTargets{TextureUploadTarget::TextureBuffer};
|
|
};
|
|
} // namespace GLState
|
|
} // namespace MG_State
|
|
} // namespace MobileGL
|