diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/brussel.common/PodVector.hpp | 104 | ||||
-rw-r--r-- | src/brussel.common/RcPtr.hpp | 2 | ||||
-rw-r--r-- | src/brussel.common/ScopedResource.hpp | 54 | ||||
-rw-r--r-- | src/brussel.engine/Material.cpp | 37 | ||||
-rw-r--r-- | src/brussel.engine/Shader.cpp | 140 | ||||
-rw-r--r-- | src/brussel.engine/Shader.hpp | 6 | ||||
-rw-r--r-- | src/brussel.engine/Shader_p.hpp | 16 |
7 files changed, 208 insertions, 151 deletions
diff --git a/src/brussel.common/PodVector.hpp b/src/brussel.common/PodVector.hpp index bd92e7d..b6ab1d6 100644 --- a/src/brussel.common/PodVector.hpp +++ b/src/brussel.common/PodVector.hpp @@ -26,20 +26,20 @@ public: mData = nullptr; } - PodVector(const PodVector<T>& src) { + PodVector(const PodVector& src) { mSize = mCapacity = 0; mData = nullptr; operator=(src); } - PodVector<T>& operator=(const PodVector<T>& src) { + PodVector& operator=(const PodVector& src) { clear(); resize(src.mSize); - std::memcpy(mData, src.mData, (size_t)mSize * sizeof(T)); + std::memcpy(mData, src.mData, static_cast<size_t>(mSize) * sizeof(T)); return *this; } - PodVector(PodVector&& src) { + PodVector(PodVector&& src) noexcept { mSize = src.mSize; mCapacity = src.mCapacity; mData = src.mData; @@ -48,7 +48,7 @@ public: src.mData = nullptr; } - PodVector& operator=(PodVector&& src) { + PodVector& operator=(PodVector&& src) noexcept { if (this != &src) { std::free(mData); @@ -66,18 +66,18 @@ public: std::free(mData); } - bool empty() const { return mSize == 0; } - int size() const { return mSize; } - int size_in_bytes() const { return mSize * (int)sizeof(T); } - int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); } - int capacity() const { return mCapacity; } + [[nodiscard]] bool empty() const { return mSize == 0; } + [[nodiscard]] int size() const { return mSize; } + [[nodiscard]] int size_in_bytes() const { return mSize * static_cast<int>(sizeof(T)); } + [[nodiscard]] static int max_size() { return std::numeric_limits<int>::max() / static_cast<int>(sizeof(T)); } + [[nodiscard]] int capacity() const { return mCapacity; } - T& operator[](int i) { + [[nodiscard]] T& operator[](int i) { assert(i >= 0 && i < mSize); return mData[i]; } - const T& operator[](int i) const { + [[nodiscard]] const T& operator[](int i) const { assert(i >= 0 && i < mSize); return mData[i]; } @@ -90,24 +90,24 @@ public: } } - T* begin() { return mData; } - const T* begin() const { return mData; } - T* end() { return mData + mSize; } - const T* end() const { return mData + mSize; } + [[nodiscard]] T* begin() { return mData; } + [[nodiscard]] const T* begin() const { return mData; } + [[nodiscard]] T* end() { return mData + mSize; } + [[nodiscard]] const T* end() const { return mData + mSize; } - T* data() { return mData; } + [[nodiscard]] T* data() { return mData; } - T& front() { + [[nodiscard]] T& front() { assert(mSize > 0); return mData[0]; } - const T& front() const { + [[nodiscard]] const T& front() const { assert(mSize > 0); return mData[0]; } - T& back() { + [[nodiscard]] T& back() { assert(mSize > 0); return mData[mSize - 1]; } @@ -117,16 +117,16 @@ public: return mData[mSize - 1]; } - void swap(PodVector<T>& rhs) { + friend void swap(PodVector& lhs, PodVector& rhs) noexcept { int rhs_size = rhs.mSize; - rhs.mSize = mSize; - mSize = rhs_size; + rhs.mSize = lhs.mSize; + lhs.mSize = rhs_size; int rhs_cap = rhs.mCapacity; - rhs.mCapacity = mCapacity; - mCapacity = rhs_cap; + rhs.mCapacity = lhs.mCapacity; + lhs.mCapacity = rhs_cap; T* rhs_mDataTmp = rhs.mData; - rhs.mData = mData; - mData = rhs_mDataTmp; + rhs.mData = lhs.mData; + lhs.mData = rhs_mDataTmp; } int grow_capacity(int sz) const { @@ -165,9 +165,9 @@ public: /// Resize a vector to a smaller mSize, guaranteed not to cause a reallocation void reserve(int newCapacity) { if (newCapacity <= mCapacity) return; - auto tmp = (T*)std::malloc((size_t)newCapacity * sizeof(T)); + auto tmp = static_cast<T*>(std::malloc(static_cast<size_t>(newCapacity) * sizeof(T))); if (mData) { - std::memcpy(tmp, mData, (size_t)mSize * sizeof(T)); + std::memcpy(tmp, mData, static_cast<size_t>(mSize) * sizeof(T)); std::free(mData); } mData = tmp; @@ -201,7 +201,10 @@ public: T* erase(const T* it) { assert(it >= mData && it < mData + mSize); const ptrdiff_t off = it - mData; - std::memmove(mData + off, mData + off + 1, ((size_t)mSize - (size_t)off - 1) * sizeof(T)); + std::memmove( + mData + off, + mData + off + 1, + (static_cast<size_t>(mSize) - static_cast<size_t>(off) - 1) * sizeof(T)); mSize--; return mData + off; } @@ -210,15 +213,22 @@ public: assert(it >= mData && it < mData + mSize && it_last > it && it_last <= mData + mSize); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - mData; - std::memmove(mData + off, mData + off + count, ((size_t)mSize - (size_t)off - count) * sizeof(T)); - mSize -= (int)count; + std::memmove( + mData + off, + mData + off + count, + (static_cast<size_t>(mSize) - static_cast<size_t>(off) - count) * sizeof(T)); + mSize -= static_cast<int>(count); return mData + off; } T* erase_unsorted(const T* it) { assert(it >= mData && it < mData + mSize); const ptrdiff_t off = it - mData; - if (it < mData + mSize - 1) std::memcpy(mData + off, mData + mSize - 1, sizeof(T)); + if (it < mData + mSize - 1) + std::memcpy( + mData + off, + mData + mSize - 1, + sizeof(T)); mSize--; return mData + off; } @@ -227,13 +237,17 @@ public: assert(it >= mData && it <= mData + mSize); const ptrdiff_t off = it - mData; if (mSize == mCapacity) reserve(grow_capacity(mSize + 1)); - if (off < (int)mSize) std::memmove(mData + off + 1, mData + off, ((size_t)mSize - (size_t)off) * sizeof(T)); + if (off < mSize) + std::memmove( + mData + off + 1, + mData + off, + (static_cast<size_t>(mSize) - static_cast<size_t>(off)) * sizeof(T)); std::memcpy(&mData[off], &v, sizeof(v)); mSize++; return mData + off; } - bool contains(const T& v) const { + [[nodiscard]] bool contains(const T& v) const { const T* data = mData; const T* dataEnd = mData + mSize; while (data < dataEnd) { @@ -242,7 +256,7 @@ public: return false; } - T* find(const T& v) { + [[nodiscard]] T* find(const T& v) { T* data = mData; const T* dataEnd = mData + mSize; while (data < dataEnd) @@ -253,14 +267,14 @@ public: return data; } - const T* find(const T& v) const { + [[nodiscard]] const T* find(const T& v) const { const T* data = mData; const T* dataEnd = mData + mSize; - while (data < dataEnd) + while (data < dataEnd) { if (*data == v) break; - else - ++data; + ++data; + } return data; } @@ -285,13 +299,13 @@ public: int index_from_ptr(const T* it) const { assert(it >= mData && it < mData + mSize); const ptrdiff_t off = it - mData; - return (int)off; + return off; } // Custom utility functions - std::span<T> as_span() { return { mData, (size_t)mSize }; } - std::span<uint8_t> as_data_span() { return { (uint8_t*)mData, (size_t)mSize * sizeof(T) }; } - std::span<const T> as_span() const { return { mData, (size_t)mSize }; } - std::span<const uint8_t> as_data_span() const { return { (uint8_t*)mData, (size_t)mSize * sizeof(T) }; } + [[nodiscard]] std::span<T> as_span() { return { mData, static_cast<size_t>(mSize) }; } + [[nodiscard]] std::span<uint8_t> as_data_span() { return { static_cast<uint8_t*>(mData), static_cast<size_t>(mSize) * sizeof(T) }; } + [[nodiscard]] std::span<const T> as_span() const { return { mData, static_cast<size_t>(mSize) }; } + [[nodiscard]] std::span<const uint8_t> as_data_span() const { return { static_cast<uint8_t*>(mData), static_cast<size_t>(mSize) * sizeof(T) }; } }; diff --git a/src/brussel.common/RcPtr.hpp b/src/brussel.common/RcPtr.hpp index e3e420e..72a9b86 100644 --- a/src/brussel.common/RcPtr.hpp +++ b/src/brussel.common/RcPtr.hpp @@ -98,7 +98,7 @@ public: template <typename TThat> bool operator==(const RcPtr<TThat>& ptr) const { - return mPtr == ptr.Get(); + return mPtr == ptr.get(); } T* Get() const { diff --git a/src/brussel.common/ScopedResource.hpp b/src/brussel.common/ScopedResource.hpp new file mode 100644 index 0000000..b4098eb --- /dev/null +++ b/src/brussel.common/ScopedResource.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <type_traits> + +/// std::unique_ptr, but for non-pointer resources +template <typename T, typename TDeleter, T kNullValue = T()> + requires std::is_trivial_v<T> && std::equality_comparable<T> +class ScopedResource { +private: + T mValue; + +public: + ScopedResource() + : mValue{ kNullValue } {} + explicit ScopedResource(T t) + : mValue{ std::move(t) } {} + + ScopedResource(const ScopedResource& that) = delete; + ScopedResource& operator=(const ScopedResource& that) = delete; + + ScopedResource(ScopedResource&& that) noexcept + : mValue(that.mValue) {} + ScopedResource& operator=(ScopedResource&& that) noexcept { + if (this == &that) + return *this; + TDeleter::DeleteObject(mValue); + mValue = that.mValue; + that.mValue = kNullValue; + return *this; + } + + ScopedResource& operator=(T newValue) { + TDeleter::DeleteObject(mValue); + mValue = newValue; + return *this; + } + + ~ScopedResource() { + TDeleter::DeleteObject(mValue); + } + + explicit operator bool() const { + return mValue != kNullValue; + } + + const T& get() const { return mValue; } + T& get() { return mValue; } + + T release() { + T tmp = mValue; + mValue = kNullValue; + return tmp; + } +}; diff --git a/src/brussel.engine/Material.cpp b/src/brussel.engine/Material.cpp index 4443ae5..21edd4d 100644 --- a/src/brussel.engine/Material.cpp +++ b/src/brussel.engine/Material.cpp @@ -230,35 +230,36 @@ void Material::SetShader(Shader* shader) { mBoundTextures.clear(); for (int i = 0; i < info.uniforms.size(); ++i) { auto& decl = info.uniforms[i]; - switch (decl->kind) { - case ShaderVariable::KD_Math: { - auto& mathDecl = static_cast<ShaderMathVariable&>(*decl); + switch (decl.index()) { + case ShaderInfo::kKindMath: { + auto& mathDecl = std::get<ShaderMathVariable>(decl); if (mathDecl.width == 1) { if (mathDecl.height == 1) { // Scalar auto& scalar = mBoundScalars.emplace_back(); - scalar.location = decl->location; + scalar.location = mathDecl.location; scalar.infoUniformIndex = i; } else { // Vector auto& vec = mBoundVectors.emplace_back(); - vec.location = decl->location; + vec.location = mathDecl.location; vec.infoUniformIndex = i; vec.actualLength = mathDecl.height; } } else { // Matrix auto& mat = mBoundMatrices.emplace_back(); - mat.location = decl->location; + mat.location = mathDecl.location; mat.infoUniformIndex = i; mat.actualWidth = mathDecl.width; mat.actualHeight = mathDecl.height; } } break; - case ShaderVariable::KD_Sampler: { + case ShaderInfo::kKindSampler: { + auto& samplerDecl = std::get<ShaderSamplerVariable>(decl); auto& uniform = mBoundTextures.emplace_back(); - uniform.location = decl->location; + uniform.location = samplerDecl.location; uniform.infoUniformIndex = i; } break; } @@ -363,7 +364,7 @@ void IresMaterial::ShowEditor(IEditor& editor) { auto shaderIres = shader->GetIres(); for (auto& field : mInstance->mBoundScalars) { - auto& decl = static_cast<ShaderMathVariable&>(*shaderInfo.uniforms[field.infoUniformIndex]); + auto& decl = std::get<ShaderMathVariable>(shaderInfo.uniforms[field.infoUniformIndex]); decl.ShowInfo(); ImGui::Indent(); @@ -377,7 +378,7 @@ void IresMaterial::ShowEditor(IEditor& editor) { ImGui::Unindent(); } for (auto& field : mInstance->mBoundVectors) { - auto& decl = static_cast<ShaderMathVariable&>(*shaderInfo.uniforms[field.infoUniformIndex]); + auto& decl = std::get<ShaderMathVariable>(shaderInfo.uniforms[field.infoUniformIndex]); decl.ShowInfo(); ImGui::Indent(); @@ -394,13 +395,13 @@ void IresMaterial::ShowEditor(IEditor& editor) { ImGui::Unindent(); } for (auto& field : mInstance->mBoundMatrices) { - auto& decl = static_cast<ShaderMathVariable&>(*shaderInfo.uniforms[field.infoUniformIndex]); + auto& decl = std::get<ShaderMathVariable>(shaderInfo.uniforms[field.infoUniformIndex]); decl.ShowInfo(); // TODO } for (auto& field : mInstance->mBoundTextures) { - auto& decl = static_cast<ShaderSamplerVariable&>(*shaderInfo.uniforms[field.infoUniformIndex]); + auto& decl = std::get<ShaderSamplerVariable>(shaderInfo.uniforms[field.infoUniformIndex]); decl.ShowInfo(); // TODO @@ -423,7 +424,7 @@ void IresMaterial::Write(IresWritingContext& ctx, rapidjson::Value& value, rapid rapidjson::Value fields(rapidjson::kArrayType); for (auto& scalar : mInstance->mBoundScalars) { rapidjson::Value rvField(rapidjson::kObjectType); - rvField.AddMember("Name", shaderInfo.uniforms[scalar.infoUniformIndex]->name, root.GetAllocator()); + rvField.AddMember("Name", std::visit([](auto&& v) { return v.name; }, shaderInfo.uniforms[scalar.infoUniformIndex]), root.GetAllocator()); rvField.AddMember("Type", "Scalar", root.GetAllocator()); switch (scalar.actualType) { case GL_FLOAT: rvField.AddMember("Value", scalar.floatValue, root.GetAllocator()); break; @@ -434,14 +435,14 @@ void IresMaterial::Write(IresWritingContext& ctx, rapidjson::Value& value, rapid } for (auto& vector : mInstance->mBoundVectors) { rapidjson::Value rvField(rapidjson::kObjectType); - rvField.AddMember("Name", shaderInfo.uniforms[vector.infoUniformIndex]->name, root.GetAllocator()); + rvField.AddMember("Name", std::visit([](auto&& v) { return v.name; }, shaderInfo.uniforms[vector.infoUniformIndex]), root.GetAllocator()); rvField.AddMember("Type", "Vector", root.GetAllocator()); rvField.AddMember("Value", MakeVectorJson(vector, root).Move(), root.GetAllocator()); fields.PushBack(rvField, root.GetAllocator()); } for (auto& matrix : mInstance->mBoundMatrices) { rapidjson::Value rvField(rapidjson::kObjectType); - rvField.AddMember("Name", shaderInfo.uniforms[matrix.infoUniformIndex]->name, root.GetAllocator()); + rvField.AddMember("Name", std::visit([](auto&& v) { return v.name; }, shaderInfo.uniforms[matrix.infoUniformIndex]), root.GetAllocator()); rvField.AddMember("Type", "Matrix", root.GetAllocator()); rvField.AddMember("Value", MakeMatrixJson(matrix, root).Move(), root.GetAllocator()); fields.PushBack(rvField, root.GetAllocator()); @@ -492,7 +493,7 @@ void IresMaterial::Read(IresLoadingContext& ctx, const rapidjson::Value& value) Material::ScalarUniform uniform; if (rvName) { TryFindShaderId(shader, rapidjson::AsStringView(*rvName), uniform.infoUniformIndex); - uniform.location = shaderInfo.uniforms[uniform.infoUniformIndex]->location; + uniform.location = std::visit([](auto&& v) { return v.location; }, shaderInfo.uniforms[uniform.infoUniformIndex]); } if (rvValue->IsFloat()) { uniform.actualType = GL_FLOAT; @@ -509,14 +510,14 @@ void IresMaterial::Read(IresLoadingContext& ctx, const rapidjson::Value& value) auto uniform = ReadVectorFromJson(*rvValue); if (rvName) { TryFindShaderId(shader, rapidjson::AsStringView(*rvName), uniform.infoUniformIndex); - uniform.location = shaderInfo.uniforms[uniform.infoUniformIndex]->location; + uniform.location = std::visit([](auto&& v) { return v.location; }, shaderInfo.uniforms[uniform.infoUniformIndex]); } mInstance->mBoundVectors.push_back(std::move(uniform)); } else if (type == "Matrix"sv) { auto uniform = ReadMatrixFromjson(*rvValue); if (rvName) { TryFindShaderId(shader, rapidjson::AsStringView(*rvName), uniform.infoUniformIndex); - uniform.location = shaderInfo.uniforms[uniform.infoUniformIndex]->location; + uniform.location = std::visit([](auto&& v) { return v.location; }, shaderInfo.uniforms[uniform.infoUniformIndex]); } mInstance->mBoundMatrices.push_back(uniform); } else if (type == "Texture"sv) { diff --git a/src/brussel.engine/Shader.cpp b/src/brussel.engine/Shader.cpp index 9bf2e0e..d795188 100644 --- a/src/brussel.engine/Shader.cpp +++ b/src/brussel.engine/Shader.cpp @@ -1,4 +1,5 @@ #include "Shader.hpp" +#include "Shader_p.hpp" #include "AppConfig.hpp" @@ -19,20 +20,23 @@ using namespace std::literals; void ShaderMathVariable::ShowInfo() const { + auto semantic = Metadata::EnumToString(this->semantic); + auto scalarType = Tags::GLTypeToString(this->scalarType); ImGui::BulletText("Location: %d\nName: %s\nSemantic: %.*s\nType: %.*s %dx%d", location, name.c_str(), - PRINTF_STRING_VIEW(Metadata::EnumToString(semantic)), - PRINTF_STRING_VIEW(Tags::GLTypeToString(scalarType)), + PRINTF_STRING_VIEW(semantic), + PRINTF_STRING_VIEW(scalarType), width, height); } void ShaderSamplerVariable::ShowInfo() const { + auto semantic = Metadata::EnumToString(this->semantic); ImGui::BulletText("Location: %d\nName: %s\nSemantic: %.*s\nType: Sampler", location, name.c_str(), - PRINTF_STRING_VIEW(Metadata::EnumToString(semantic))); + PRINTF_STRING_VIEW(semantic)); } namespace ProjectBrussel_UNITY_ID { @@ -66,12 +70,12 @@ void InitAutoFills(Shader& shader) { } } // namespace ProjectBrussel_UNITY_ID -GLuint ShaderInfo::FindInputLocation(Tags::VertexElementSemantic semantic) { +GLuint ShaderInfo::FindInputLocation(Tags::VertexElementSemantic semantic) const { using namespace ProjectBrussel_UNITY_ID; return FindLocation(inputs, semantic); } -GLuint ShaderInfo::FindOutputLocation(Tags::VertexElementSemantic semantic) { +GLuint ShaderInfo::FindOutputLocation(Tags::VertexElementSemantic semantic) const { using namespace ProjectBrussel_UNITY_ID; return FindLocation(outputs, semantic); } @@ -85,31 +89,35 @@ Shader::~Shader() { namespace ProjectBrussel_UNITY_ID { // Grabs section [begin, end) -Shader::ErrorCode CreateShader(GLuint& out, const char* src, int beginIdx, int endIdx, GLenum type) { - out = glCreateShader(type); +Shader::ErrorCode CreateShader(OGLShader& out, const char* src, int beginIdx, int endIdx, GLenum type) { + GLuint shader = glCreateShader(type); const GLchar* begin = &src[beginIdx]; const GLint len = endIdx - beginIdx; - glShaderSource(out, 1, &begin, &len); + glShaderSource(shader, 1, &begin, &len); - glCompileShader(out); + glCompileShader(shader); GLint compileStatus; - glGetShaderiv(out, GL_COMPILE_STATUS, &compileStatus); + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); if (compileStatus == GL_FALSE) { GLint len; - glGetShaderiv(out, GL_INFO_LOG_LENGTH, &len); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); std::string log(len, '\0'); - glGetShaderInfoLog(out, len, nullptr, log.data()); + glGetShaderInfoLog(shader, len, nullptr, log.data()); - return Shader ::EC_CompilationFailed; + std::fprintf(stderr, "Error compiling shader: %s", log.c_str()); + + glDeleteShader(shader); + return Shader::EC_CompilationFailed; } + out = shader; return Shader::EC_Success; } -Shader::ErrorCode CreateShader(GLuint& out, std::string_view str, GLenum type) { - return CreateShader(out, str.data(), 0, str.size(), type); +Shader::ErrorCode CreateShader(OGLShader& out, std::string_view str, GLenum type) { + return CreateShader(out, str.data(), 0, static_cast<int>(str.size()), type); } Shader::ErrorCode LinkShaderProgram(GLuint program) { @@ -144,58 +152,41 @@ Shader::ErrorCode Shader::InitFromSources(const ShaderSources& sources) { return EC_AlreadyInitialized; } - GLuint program = glCreateProgram(); - ScopeGuard sg = [&]() { glDeleteProgram(program); }; + OGLShaderProgram program(glCreateProgram()); - GLuint vertex = 0; - DEFER { - glDeleteShader(vertex); - }; + OGLShader vertex; if (!sources.vertex.empty()) { CATCH_ERROR(CreateShader(vertex, sources.vertex, GL_VERTEX_SHADER)); - glAttachShader(program, vertex); + glAttachShader(program.get(), vertex.get()); } - GLuint geometry = 0; - DEFER { - glDeleteShader(geometry); - }; + OGLShader geometry; if (!sources.geometry.empty()) { CATCH_ERROR(CreateShader(geometry, sources.geometry, GL_GEOMETRY_SHADER)); - glAttachShader(program, geometry); + glAttachShader(program.get(), geometry.get()); } - GLuint tessControl = 0; - DEFER { - glDeleteShader(tessControl); - }; + OGLShader tessControl; if (!sources.tessControl.empty()) { CATCH_ERROR(CreateShader(tessControl, sources.tessControl, GL_TESS_CONTROL_SHADER)); - glAttachShader(program, tessControl); + glAttachShader(program.get(), tessControl.get()); } - GLuint tessEval = 0; - DEFER { - glDeleteShader(tessEval); - }; + OGLShader tessEval; if (!sources.tessEval.empty()) { CATCH_ERROR(CreateShader(tessEval, sources.tessEval, GL_TESS_EVALUATION_SHADER)); - glAttachShader(program, tessEval); + glAttachShader(program.get(), tessEval.get()); } - GLuint fragment = 0; - DEFER { - glDeleteShader(fragment); - }; + OGLShader fragment; if (!sources.fragment.empty()) { CATCH_ERROR(CreateShader(fragment, sources.fragment, GL_FRAGMENT_SHADER)); - glAttachShader(program, fragment); + glAttachShader(program.get(), fragment.get()); } - CATCH_ERROR(LinkShaderProgram(program)); + CATCH_ERROR(LinkShaderProgram(program.get())); - sg.Dismiss(); - mProgram = program; + mProgram = program.release(); InitAutoFills(*this); @@ -205,30 +196,11 @@ Shader::ErrorCode Shader::InitFromSources(const ShaderSources& sources) { Shader::ErrorCode Shader::InitFromSource(std::string_view source) { using namespace ProjectBrussel_UNITY_ID; - GLuint vertex = 0; - DEFER { - glDeleteShader(vertex); - }; - - GLuint geometry = 0; - DEFER { - glDeleteShader(geometry); - }; - - GLuint tessControl = 0; - DEFER { - glDeleteShader(tessControl); - }; - - GLuint tessEval = 0; - DEFER { - glDeleteShader(tessEval); - }; - - GLuint fragment = 0; - DEFER { - glDeleteShader(fragment); - }; + OGLShader vertex; + OGLShader geometry; + OGLShader tessControl; + OGLShader tessEval; + OGLShader fragment; int prevBegin = -1; // Excluding #type marker int prevEnd = -1; // [begin, end) @@ -240,15 +212,15 @@ Shader::ErrorCode Shader::InitFromSource(std::string_view source) { return EC_Success; } - if (prevShaderVariant == "vertex" && !vertex) { + if (prevShaderVariant == "vertex" && vertex.get() == 0) { CATCH_ERROR(CreateShader(vertex, source.data(), prevBegin, prevEnd, GL_VERTEX_SHADER)); - } else if (prevShaderVariant == "geometry" && !geometry) { + } else if (prevShaderVariant == "geometry" && geometry.get() == 0) { CATCH_ERROR(CreateShader(geometry, source.data(), prevBegin, prevEnd, GL_GEOMETRY_SHADER)); - } else if (prevShaderVariant == "tessellation_control" && !tessControl) { + } else if (prevShaderVariant == "tessellation_control" && tessControl.get() == 0) { CATCH_ERROR(CreateShader(tessControl, source.data(), prevBegin, prevEnd, GL_TESS_CONTROL_SHADER)); - } else if (prevShaderVariant == "tessellation_evaluation" && !tessEval) { + } else if (prevShaderVariant == "tessellation_evaluation" && tessEval.get() == 0) { CATCH_ERROR(CreateShader(tessEval, source.data(), prevBegin, prevEnd, GL_TESS_EVALUATION_SHADER)); - } else if (prevShaderVariant == "fragment" && !fragment) { + } else if (prevShaderVariant == "fragment" && fragment.get() == 0) { CATCH_ERROR(CreateShader(fragment, source.data(), prevBegin, prevEnd, GL_FRAGMENT_SHADER)); } else { return EC_InvalidShaderVariant; @@ -312,19 +284,17 @@ Shader::ErrorCode Shader::InitFromSource(std::string_view source) { prevEnd = static_cast<int>(source.size()); CATCH_ERROR(CommitSection()); - GLuint program = glCreateProgram(); - ScopeGuard sg = [&]() { glDeleteProgram(program); }; + OGLShaderProgram program(glCreateProgram()); - if (vertex) glAttachShader(program, vertex); - if (geometry) glAttachShader(program, geometry); - if (tessControl) glAttachShader(program, tessControl); - if (tessEval) glAttachShader(program, tessEval); - if (fragment) glAttachShader(program, fragment); + if (vertex) glAttachShader(program.get(), vertex.get()); + if (geometry) glAttachShader(program.get(), geometry.get()); + if (tessControl) glAttachShader(program.get(), tessControl.get()); + if (tessEval) glAttachShader(program.get(), tessEval.get()); + if (fragment) glAttachShader(program.get(), fragment.get()); - CATCH_ERROR(LinkShaderProgram(program)); + CATCH_ERROR(LinkShaderProgram(program.get())); - sg.Dismiss(); - mProgram = program; + mProgram = program.release(); InitAutoFills(*this); @@ -610,7 +580,7 @@ void IresShader::Write(IresWritingContext& ctx, rapidjson::Value& value, rapidjs using namespace ProjectBrussel_UNITY_ID; IresObject::Write(ctx, value, root); - json_dto::json_output_t out( value, root.GetAllocator() ); + json_dto::json_output_t out(value, root.GetAllocator()); out << mInstance->mInfo; } diff --git a/src/brussel.engine/Shader.hpp b/src/brussel.engine/Shader.hpp index cb980cd..14480cd 100644 --- a/src/brussel.engine/Shader.hpp +++ b/src/brussel.engine/Shader.hpp @@ -75,10 +75,12 @@ struct ShaderInfo { std::vector<ShaderMathVariable> inputs; std::vector<ShaderMathVariable> outputs; std::vector<std::variant<ShaderMathVariable, ShaderSamplerVariable>> uniforms; + static constexpr int kKindMath = 0; + static constexpr int kKindSampler = 1; // Find the first variable with the matching semantic - GLuint FindInputLocation(Tags::VertexElementSemantic semantic); - GLuint FindOutputLocation(Tags::VertexElementSemantic semantic); + GLuint FindInputLocation(Tags::VertexElementSemantic semantic) const; + GLuint FindOutputLocation(Tags::VertexElementSemantic semantic) const; template <typename TJsonIo> void json_io(TJsonIo& io) { diff --git a/src/brussel.engine/Shader_p.hpp b/src/brussel.engine/Shader_p.hpp new file mode 100644 index 0000000..81a6603 --- /dev/null +++ b/src/brussel.engine/Shader_p.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "ScopedResource.hpp" + +#include <glad/glad.h> + +struct OGLShaderDeleter { + static void DeleteObject(GLuint id) { glDeleteShader(id); } +}; + +struct OGLShaderProgramDeleter { + static void DeleteObject(GLuint id) { glDeleteProgram(id); } +}; + +using OGLShader = ScopedResource<GLuint, OGLShaderDeleter, 0>; +using OGLShaderProgram = ScopedResource<GLuint, OGLShaderProgramDeleter, 0>; |