[Feat|Fix] (...): Add/Fix lots of stuff, being able not to crash in MC.

This commit is contained in:
BZLZHH
2025-10-06 16:08:35 +08:00
parent e37dedb72d
commit bd1056f9c9
36 changed files with 1164 additions and 201 deletions
@@ -9,9 +9,9 @@ namespace MobileGL {
: m_texture(texture), m_textureLevel(level) {}
FramebufferAttachment::FramebufferAttachment(SharedPtr<RenderbufferObjectStub> renderbuffer)
: m_renderbuffer(renderbuffer) {}
FramebufferAttachment::FramebufferAttachment(std::nullptr_t)
: m_texture(nullptr), m_renderbuffer(nullptr) {}
FramebufferAttachment::FramebufferAttachment() : m_texture(nullptr), m_renderbuffer(nullptr) {}
FramebufferAttachment::FramebufferAttachment(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
m_isValid = IsValid;
}
Bool FramebufferAttachment::IsTexture() const {
return m_texture != nullptr;
@@ -39,10 +39,13 @@ namespace MobileGL {
Bool FramebufferAttachment::IsComplete() const {
if (IsTexture()) {
return m_texture->IsComplete();
Bool complete = m_texture->IsComplete();
return complete;
} else if (IsRenderbuffer()) {
// TODO
return false;
}
return false;
}
@@ -55,9 +58,13 @@ namespace MobileGL {
return {0, 0};
}
Bool FramebufferAttachment::IsValid() const {
return m_isValid;
}
// FramebufferObject
FramebufferObject::FramebufferObject() {
m_attachments.fill(FramebufferAttachment(nullptr));
m_attachments.fill(FramebufferAttachment(false));
}
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture,
@@ -73,7 +80,7 @@ namespace MobileGL {
}
void FramebufferObject::Detach(FramebufferAttachmentType type) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(nullptr);
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(false);
m_drawBuffersDirty = true;
}
@@ -86,21 +93,30 @@ namespace MobileGL {
return false;
}
int width = -1, height = -1;
for (const auto& attachment : m_attachments) {
Int width = -1, height = -1;
Int validAttachmentCount = 0;
for (SizeT i = 0; i < m_attachments.size(); ++i) {
if (!m_attachments[i].IsValid()) continue;
++validAttachmentCount;
const auto& attachment = m_attachments[i];
auto attachmentSize = attachment.GetSize();
int w = attachmentSize.x();
int h = attachmentSize.y();
Int w = attachmentSize.x();
Int h = attachmentSize.y();
if (width == -1) {
width = w;
height = h;
} else if (width != w || height != h) {
return false;
}
if (!attachment.IsComplete()) {
return false;
}
}
if (validAttachmentCount == 0) return false;
return true;
}
@@ -46,7 +46,6 @@ namespace MobileGL {
Color31,
Depth,
Stencil,
DepthStencil,
FramebufferAttachmentTypeCount,
Unknown = -1
};
@@ -60,8 +59,7 @@ namespace MobileGL {
// TODO: add Renderbuffer when it is implemented
explicit FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0);
explicit FramebufferAttachment(SharedPtr<RenderbufferObjectStub> renderbuffer);
explicit FramebufferAttachment(std::nullptr_t);
explicit FramebufferAttachment();
explicit FramebufferAttachment(Bool IsValid = true);
Bool IsTexture() const;
Bool IsRenderbuffer() const;
@@ -71,11 +69,13 @@ namespace MobileGL {
Int GetTextureLevel() const;
Bool IsComplete() const;
IntVec3 GetSize() const;
Bool IsValid() const;
private:
SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr;
SharedPtr<RenderbufferObjectStub> m_renderbuffer = nullptr;
Int m_textureLevel = 0;
Bool m_isValid = true;
};
class FramebufferObject {
@@ -1,13 +1,18 @@
#include "FramebufferState.h"
#include "MG_State/GLState/FramebufferState/FramebufferObject.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
FramebufferState::FramebufferState() {}
FramebufferState::FramebufferState() {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
m_bindingSlots[i] = BindingSlot<FramebufferObject>(static_cast<FramebufferTarget>(i));
}
}
SharedPtr<FramebufferObject> FramebufferState::GetFramebufferObject(Uint index) {
auto it = m_bufferObjects.find(index);
if (it != m_bufferObjects.end()) {
auto it = m_framebufferObjects.find(index);
if (it != m_framebufferObjects.end()) {
return it->second;
}
return nullptr;
@@ -20,8 +25,15 @@ namespace MobileGL {
}
SharedPtr<FramebufferObject> FramebufferState::CreateFramebufferObject(Uint index) {
if (index == 0) {
if (!m_indexGenerator.IsValid(0)) {
m_indexGenerator.Insert(0);
} else {
return nullptr;
}
}
auto bufferObject = MakeShared<FramebufferObject>();
m_bufferObjects[index] = bufferObject;
m_framebufferObjects[index] = bufferObject;
return bufferObject;
}
@@ -37,14 +49,14 @@ namespace MobileGL {
void FramebufferState::MarkFramebufferObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) {
auto it = m_bufferObjects.find(index);
if (it != m_bufferObjects.end()) {
auto it = m_framebufferObjects.find(index);
if (it != m_framebufferObjects.end()) {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
if (m_bindingSlots[i].GetBoundObject() == it->second) {
m_bindingSlots[i].Bind(nullptr);
}
}
m_bufferObjects.erase(it);
m_framebufferObjects.erase(it);
}
m_indexGenerator.Delete(index);
}
@@ -55,7 +67,7 @@ namespace MobileGL {
}
Bool FramebufferState::ValidateFramebufferObject(Uint index) const {
return m_bufferObjects.find(index) != m_bufferObjects.end();
return m_framebufferObjects.find(index) != m_framebufferObjects.end();
}
} // namespace GLState
} // namespace MG_State
@@ -20,7 +20,7 @@ namespace MobileGL {
Bool ValidateFramebufferObject(Uint index) const;
private:
UnorderedMap<Uint, SharedPtr<FramebufferObject>> m_bufferObjects;
UnorderedMap<Uint, SharedPtr<FramebufferObject>> m_framebufferObjects;
IndexGenerator<Uint> m_indexGenerator;
Array<BindingSlot<FramebufferObject>, static_cast<SizeT>(FramebufferTarget::FramebufferTargetCount)>
m_bindingSlots;
@@ -1,7 +1,6 @@
#include "ProgramObject.h"
#include <MG_Util/ShaderTranspiler/ShaderCompiler.h>
#include "MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.h"
#include <MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.h>
namespace MobileGL {
namespace MG_State {
@@ -74,7 +73,9 @@ namespace MobileGL {
for (int i = 0; i < m_activeUniformCount; i++) {
auto& uniform = m_program->getUniform(i);
auto location = uniform.layoutLocation();
m_maxUniformLocation = std::max(m_maxUniformLocation, location);
if (location >= 0) {
m_maxUniformLocation = std::max(m_maxUniformLocation, location);
}
m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)uniform.name.length());
m_uniformLocations[uniform.name] = location;
}
@@ -88,37 +89,97 @@ namespace MobileGL {
for (int i = 0; i < m_activeUniformCount; i++) {
auto& uniform = m_program->getUniform(i);
auto location = uniform.layoutLocation();
m_uniformNames[location] = uniform.name;
m_uniformTypes[location] = uniform.glDefineType;
m_uniformIsOpaqueType[location] = uniform.getType()->isOpaque();
m_uniformArraySizes[location] = uniform.size;
}
// attributes (pipe in)
int inCount = m_program->getNumPipeInputs();
m_attribs.resize(inCount);
m_attribTypes.resize(inCount);
// Get locations parsed in program
for (int i = 0; i < inCount; i++) {
auto& inVar = m_program->getPipeInput(i);
auto location = inVar.layoutLocation();
m_attribInNameMaxLength = std::max(m_attribInNameMaxLength, (Int)inVar.name.length());
m_attribs[location] = inVar.name;
m_attribTypes[location] = inVar.glDefineType;
}
// Implement glBindAttribLocation semantics
for (auto& [name, location] : m_explicitAttribLocations) {
assert(location < m_attribs.size());
if (m_attribs[location] != name) {
auto it = std::find(m_attribs.begin(), m_attribs.end(), name);
if (it == m_attribs.end()) continue;
std::swap(m_attribs[location], m_attribs[std::distance(m_attribs.begin(), it)]);
std::swap(m_attribTypes[location], m_attribTypes[std::distance(m_attribs.begin(), it)]);
if (location >= 0 && location < (int)m_uniformNames.size()) {
m_uniformNames[location] = uniform.name;
m_uniformTypes[location] = uniform.glDefineType;
m_uniformIsOpaqueType[location] = uniform.getType()->isOpaque();
m_uniformArraySizes[location] = uniform.size;
}
}
// UBO
int inCount = m_program->getNumPipeInputs();
int maxLoc = -1;
for (int i = 0; i < inCount; ++i) {
int loc = m_program->getPipeInput(i).layoutLocation();
if (loc >= 0) maxLoc = std::max(maxLoc, loc);
}
if (maxLoc < 0) {
maxLoc = std::max(0, inCount - 1);
}
GLint maxAttribs = 16; // TODO: get from backend
if (maxLoc >= maxAttribs) {
MGLOG_W("ProgramObject::DoReflection - required attrib location %d >= GL_MAX_VERTEX_ATTRIBS (%d). "
"Clamping.",
maxLoc, maxAttribs);
maxLoc = maxAttribs - 1;
}
m_attribs.resize(maxLoc + 1);
m_attribTypes.resize(maxLoc + 1);
for (int i = 0; i < inCount; ++i) {
auto& inVar = m_program->getPipeInput(i);
int location = inVar.layoutLocation();
m_attribInNameMaxLength = std::max(m_attribInNameMaxLength, (Int)inVar.name.length());
if (location >= 0 && location < (int)m_attribs.size()) {
m_attribs[location] = inVar.name;
m_attribTypes[location] = inVar.glDefineType;
} else if (location >= (int)m_attribs.size()) {
MGLOG_W("ProgramObject::DoReflection - attrib location %d >= attribs.size() (%zu). Ignoring.",
location, m_attribs.size());
continue;
} else {
bool placed = false;
for (size_t idx = 0; idx < m_attribs.size(); ++idx) {
if (m_attribs[idx].empty()) {
m_attribs[idx] = inVar.name;
m_attribTypes[idx] = inVar.glDefineType;
placed = true;
break;
}
}
if (!placed && (int)m_attribs.size() < maxAttribs) {
m_attribs.push_back(inVar.name);
m_attribTypes.push_back(inVar.glDefineType);
placed = true;
}
if (!placed) {
MGLOG_W("ProgramObject::DoReflection - cannot place attrib '%s' (no free slot and at max "
"capacity). Ignoring.",
inVar.name.c_str());
}
}
}
// Implement glBindAttribLocation semantics (explicit locations set by user)
for (auto& [name, location] : m_explicitAttribLocations) {
if (location < 0) continue;
if (location >= (int)m_attribs.size()) {
if (location >= maxAttribs) {
MGLOG_W("SetExplicitAttribLocation: requested location %d >= GL_MAX_VERTEX_ATTRIBS (%d). "
"Ignored for attribute '%s'.",
location, maxAttribs, name.c_str());
continue;
}
m_attribs.resize(location + 1);
m_attribTypes.resize(location + 1);
}
if (m_attribs[location] != name) {
auto it = std::find(m_attribs.begin(), m_attribs.end(), name);
if (it == m_attribs.end()) continue;
auto idx = std::distance(m_attribs.begin(), it);
std::swap(m_attribs[location], m_attribs[idx]);
std::swap(m_attribTypes[location], m_attribTypes[idx]);
}
}
// ---------- UBO ----------
int uboCount = m_program->getNumUniformBlocks();
for (int i = 0; i < uboCount; i++) {
auto& ubo = m_program->getUniformBlock(i);
@@ -1,7 +1,6 @@
#include "ShaderObject.h"
#include <MG_Util/ShaderTranspiler/ShaderCompiler.h>
#include "MG_Util/ShaderTranspiler/glslang/UniformTraverser.h"
#include <MG_Util/ShaderTranspiler/glslang/UniformTraverser.h>
namespace MobileGL {
namespace MG_State {
@@ -33,7 +33,7 @@ namespace MobileGL {
Unknown = -1
};
enum class CompareFunc {
enum class SamplerCompareFunc {
Never,
Less,
Equal,
@@ -42,7 +42,7 @@ namespace MobileGL {
NotEqual,
GreaterEqual,
Always,
CompareFuncCount,
SamplerCompareFuncCount,
Unknown = -1
};
@@ -55,7 +55,7 @@ namespace MobileGL {
m_wrapR(SamplerWrapMode::Repeat), m_minFilter(SamplerFilterMode::Linear),
m_magFilter(SamplerFilterMode::Linear), m_mipmapMode(SamplerMipmapMode::None), m_minLod(0.0f),
m_maxLod(1000.0f), m_lodBias(0.0f), m_compareMode(SamplerCompareMode::None),
m_compareFunc(CompareFunc::Less) {}
m_compareFunc(SamplerCompareFunc::Less) {}
void SetWrapS(SamplerWrapMode mode) { m_wrapS = mode; }
void SetWrapT(SamplerWrapMode mode) { m_wrapT = mode; }
@@ -71,7 +71,7 @@ namespace MobileGL {
m_maxLod = maxLod;
}
void SetLodBias(Float bias) { m_lodBias = bias; }
void SetCompareFunc(CompareFunc func) { m_compareFunc = func; }
void SetSamplerCompareFunc(SamplerCompareFunc func) { m_compareFunc = func; }
void SetCompareMode(SamplerCompareMode mode) { m_compareMode = mode; }
SamplerWrapMode GetWrapS() const { return m_wrapS; }
@@ -84,7 +84,7 @@ namespace MobileGL {
Float GetMaxLod() const { return m_maxLod; }
Float GetLodBias() const { return m_lodBias; }
SamplerCompareMode GetCompareMode() const { return m_compareMode; }
CompareFunc GetCompareFunc() const { return m_compareFunc; }
SamplerCompareFunc GetSamplerCompareFunc() const { return m_compareFunc; }
private:
SamplerWrapMode m_wrapS, m_wrapT, m_wrapR;
@@ -93,7 +93,7 @@ namespace MobileGL {
Float m_minLod, m_maxLod;
Float m_lodBias;
SamplerCompareMode m_compareMode;
CompareFunc m_compareFunc;
SamplerCompareFunc m_compareFunc;
};
} // namespace GLState
} // namespace MG_State
@@ -5,7 +5,9 @@ namespace MobileGL {
namespace MG_State {
namespace GLState {
// TextureObjectBase implementations
TextureObjectBase::TextureObjectBase(TextureTarget target) : m_target(target), m_sampler(nullptr) {}
TextureObjectBase::TextureObjectBase(TextureTarget target) : m_target(target) {
m_sampler = MakeShared<SamplerObject>();
}
void TextureObjectBase::SetMipmapLevel(const MipmapLevelInput& level) {
SetMipmapImpl(level);
@@ -38,14 +40,18 @@ namespace MobileGL {
if (m_internalFormat == TextureInternalFormat::Unknown) {
return false;
}
if (m_mipmaps.empty()) {
return false;
}
for (const auto& level : m_mipmaps) {
for (size_t i = 0; i < m_mipmaps.size(); ++i) {
const auto& level = m_mipmaps[i];
if (level.size.x() <= 0 || level.size.y() <= 0 || level.size.z() <= 0) {
return false;
}
}
// TODO: add more completeness checks based on texture type and mipmap levels
return true;
}
@@ -1,8 +1,7 @@
#pragma once
#include "SamplerObject.h"
#include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
#include "MG_Util/Types.h"
#include "SamplerObject.h"
namespace MobileGL {
enum class TextureTarget {
@@ -197,6 +196,7 @@ namespace MobileGL {
}
};
// TODO: BaseLevel, MaxLevel, Swizzle
class ITextureObject {
public:
using TargetEnum = TextureTarget;