diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp new file mode 100644 index 0000000..1598f69 --- /dev/null +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp @@ -0,0 +1,426 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#include "OpenGLCommandBuffer.h" + +#include "Prism/Renderer/Texture.h" +#include "Prism/Renderer/StorageBuffer.h" + +namespace Prism +{ + GLenum OpenGLCommandBuffer::MapCompareOp(const CompareOp Option) + { + switch (Option) { + case CompareOp::Never: return GL_NEVER; + case CompareOp::Less: return GL_LESS; + case CompareOp::Equal: return GL_EQUAL; + case CompareOp::LessEqual: return GL_LEQUAL; + case CompareOp::Greater: return GL_GREATER; + case CompareOp::NotEqual: return GL_NOTEQUAL; + case CompareOp::GreaterEqual: return GL_GEQUAL; + case CompareOp::Always: return GL_ALWAYS; + } + return GL_ALWAYS; + } + + GLenum OpenGLCommandBuffer::MapStencilOp(const StencilOp Option) + { + switch (Option) { + case StencilOp::Keep: return GL_KEEP; + case StencilOp::Zero: return GL_ZERO; + case StencilOp::Replace: return GL_REPLACE; + case StencilOp::Incr: return GL_INCR; + case StencilOp::Decr: return GL_DECR; + case StencilOp::Invert: return GL_INVERT; + case StencilOp::IncrWrap: return GL_INCR_WRAP; + case StencilOp::DecrWrap: return GL_DECR_WRAP; + } + return GL_KEEP; + } + + GLenum OpenGLCommandBuffer::MapCullMode(CullMode mode) + { + switch (mode) { + case CullMode::None: return GL_NONE; + case CullMode::Front: return GL_FRONT; + case CullMode::Back: return GL_BACK; + } + return GL_BACK; + } + + GLenum OpenGLCommandBuffer::MapPolygonMode(PolygonMode mode) + { + switch (mode) { + case PolygonMode::Fill: return GL_FILL; + case PolygonMode::Line: return GL_LINE; + case PolygonMode::Point: return GL_POINT; + } + return GL_FILL; + } + + GLenum OpenGLCommandBuffer::MapPrimitiveType(PrimitiveType type) + { + switch (type) { + case PrimitiveType::Triangles: return GL_TRIANGLES; + case PrimitiveType::Lines: return GL_LINES; + case PrimitiveType::Points: return GL_POINTS; + } + return GL_TRIANGLES; + } + + void OpenGLCommandBuffer::SetViewport(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const + { + glViewport(x, y, width, height); + } + + void OpenGLCommandBuffer::SetScissor(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const + { + glScissor(x, y, width, height); + } + + void OpenGLCommandBuffer::SetDepthTest(const bool enable) const + { + if (enable) glEnable(GL_DEPTH_TEST); + else glDisable(GL_DEPTH_TEST); + } + + void OpenGLCommandBuffer::SetDepthFunc(const CompareOp func) const + { + glDepthFunc(MapCompareOp(func)); + } + + void OpenGLCommandBuffer::SetStencilTest(const bool enable) const + { + if (enable) glEnable(GL_STENCIL_TEST); + else glDisable(GL_STENCIL_TEST); + } + + void OpenGLCommandBuffer::SetStencilOp(const StencilOp fail, const StencilOp zFail, const StencilOp zPass) const + { + glStencilOp(MapStencilOp(fail), MapStencilOp(zFail), MapStencilOp(zPass)); + } + + void OpenGLCommandBuffer::SetStencilMask(uint32_t mask) const + { + glStencilMask(mask); + } + + void OpenGLCommandBuffer::SetCullMode(CullMode mode) const + { + if (mode == CullMode::None) glDisable(GL_CULL_FACE); + else { + glEnable(GL_CULL_FACE); + glCullFace(MapCullMode(mode)); + } + } + + void OpenGLCommandBuffer::SetPolygonMode(PolygonMode mode) const + { + glPolygonMode(GL_FRONT_AND_BACK, MapPolygonMode(mode)); + } + + void OpenGLCommandBuffer::SetLineWidth(const float width) const + { + glLineWidth(width); + } + + void OpenGLCommandBuffer::SetLineThickness(const float thickness) const + { + glLineWidth(thickness); + } + + void OpenGLCommandBuffer::SetPointSize(float size) const + { + glPointSize(size); + } + + void OpenGLCommandBuffer::BindFramebuffer(const RendererID rendererId) const + { + glBindFramebuffer(GL_FRAMEBUFFER, rendererId); + } + + GLuint FramebufferTargetToOpenGL(const FramebufferTarget target) + { + switch (target) + { + case FramebufferTarget::Draw: return GL_DRAW_FRAMEBUFFER; + case FramebufferTarget::Read: return GL_READ_FRAMEBUFFER; + case FramebufferTarget::Both: return GL_FRAMEBUFFER; + } + + return 0; + } + + void OpenGLCommandBuffer::BindFramebuffer(const FramebufferTarget target, const RendererID rendererId) const + { + glBindFramebuffer(FramebufferTargetToOpenGL(target), rendererId); + } + + void OpenGLCommandBuffer::BindTexture(const uint32_t slot, const uint32_t textureID) const + { + glBindTextureUnit(slot, textureID); + } + + static GLenum MapAccessMode(AccessMode mode) { + switch (mode) { + case AccessMode::ReadOnly: return GL_READ_ONLY; + case AccessMode::WriteOnly: return GL_WRITE_ONLY; + case AccessMode::ReadWrite: return GL_READ_WRITE; + } + return GL_READ_WRITE; + } + + static GLenum MapTextureFormat(TextureFormat format) { + switch (format) + { + case TextureFormat::RGB: return GL_RGB8; + case TextureFormat::RGBA: return GL_RGBA8; + case TextureFormat::RGBA16F: return GL_RGBA16F; + } + return GL_RGBA8; + } + + void OpenGLCommandBuffer::BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const + { + const GLenum glAccess = MapAccessMode(access); // 将 AccessMode 转为 GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE + const GLenum glFormat = MapTextureFormat(format); // 将 TextureFormat 转为 GL_RGBA16F 等内部格式 + glBindImageTexture(unit, textureID, level, layered ? GL_TRUE : GL_FALSE, layer, glAccess, glFormat); + } + + void OpenGLCommandBuffer::BindTextureUnit(uint32_t i, RendererID rendererId) const + { + glBindTextureUnit(i, rendererId); + } + + void OpenGLCommandBuffer::BindSampler(uint32_t slot, uint32_t samplerID) const + { + glBindSampler(slot, samplerID); + } + + void OpenGLCommandBuffer::SetDrawBuffer(const uint32_t attachment) const + { + glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachment); + } + + void OpenGLCommandBuffer::SetReadBuffer(const uint32_t attachment) const + { + glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment); + } + + GLuint BufferFormatToOpenGL(const BufferFormat format) + { + switch (format) { + case BufferFormat::R32UI: return GL_R32UI; + case BufferFormat::RGB16F: return GL_RGB16F; + } + return GL_RGB16F; + } + + GLuint PixelFormatToOpenGL(const PixelFormat format) + { + switch (format) { + case PixelFormat::RED: return GL_RED; + case PixelFormat::RGBA: return GL_RGBA; + } + return GL_RGBA; + } + + GLuint DataTypeToOpenGL(const DataType type) + { + switch (type) + { + case DataType::UnsignedInt: return GL_UNSIGNED_INT; + } + + return GL_UNSIGNED_INT; + } + + void OpenGLCommandBuffer::ClearBufferData(Ref buffer, BufferFormat internalFormat, + PixelFormat format, DataType type, const void* data) const + { + glClearNamedBufferData(buffer->GetRendererID(), BufferFormatToOpenGL(internalFormat), PixelFormatToOpenGL(format), DataTypeToOpenGL(type), data); + } + + void OpenGLCommandBuffer::GenerateMipmap(const uint32_t textureID) const + { + glGenerateTextureMipmap(textureID); + } + + void OpenGLCommandBuffer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, const bool faceCulling) const + { + if (!depthTest) + { + glDisable(GL_DEPTH_TEST); + } + + GLenum glPrimitiveType = 0; + switch (type) + { + case PrimitiveType::Triangles: + glPrimitiveType = GL_TRIANGLES; + break; + case PrimitiveType::Lines: + glPrimitiveType = GL_LINES; + break; + case PrimitiveType::Points: + break; + } + + if (faceCulling) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr); + + if (!depthTest) + { + glEnable(GL_DEPTH_TEST); + } + } + + void OpenGLCommandBuffer::DrawIndexed(const PrimitiveType type, const uint32_t indexCount, const uint32_t instanceCount, const uint32_t firstIndex, const int32_t vertexOffset, uint32_t firstInstance) const + { + const GLenum glType = MapPrimitiveType(type); + + const void* offset = (void*)(firstIndex * sizeof(uint32_t)); + glDrawElementsInstancedBaseVertex(glType, indexCount, GL_UNSIGNED_INT, offset, instanceCount, vertexOffset); + } + + void OpenGLCommandBuffer::Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, + uint32_t firstInstance) const + { + glDrawArraysInstancedBaseInstance(MapPrimitiveType(type), firstVertex, vertexCount, instanceCount, firstInstance); + } + + void OpenGLCommandBuffer::DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const + { + glDispatchCompute(groupX, groupY, groupZ); + } + + + GLuint MemoryBarrierMaskToOpenGLFormat(MemoryBarrierMask barrier) + { + switch (barrier) + { + case MemoryBarrierMask::VertexAttribArray: return GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; + case MemoryBarrierMask::ElementArray: return GL_ELEMENT_ARRAY_BARRIER_BIT; + case MemoryBarrierMask::Uniform: return GL_UNIFORM_BARRIER_BIT; + case MemoryBarrierMask::TextureFetch: return GL_TEXTURE_FETCH_BARRIER_BIT; + case MemoryBarrierMask::ShaderImageAccess: return GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; + case MemoryBarrierMask::Command: return GL_COMMAND_BARRIER_BIT; + case MemoryBarrierMask::PixelBuffer: return GL_PIXEL_BUFFER_BARRIER_BIT; + case MemoryBarrierMask::TextureUpdate: return GL_TEXTURE_UPDATE_BARRIER_BIT; + case MemoryBarrierMask::BufferUpdate: return GL_BUFFER_UPDATE_BARRIER_BIT; + case MemoryBarrierMask::Framebuffer: return GL_FRAMEBUFFER_BARRIER_BIT; + case MemoryBarrierMask::TransformFeedback: return GL_TRANSFORM_FEEDBACK_BARRIER_BIT; + case MemoryBarrierMask::AtomicCounter: return GL_ATOMIC_COUNTER_BARRIER_BIT; + case MemoryBarrierMask::ShaderStorage: return GL_SHADER_STORAGE_BARRIER_BIT; + case MemoryBarrierMask::None: return 0; + } + return 0; + } + + + void OpenGLCommandBuffer::MemoryBarrier(const MemoryBarrierMask barriers) const + { + glMemoryBarrier(MemoryBarrierMaskToOpenGLFormat(barriers)); + } + + void OpenGLCommandBuffer::Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const + { + GLbitfield mask = 0; + if (clearColor) { + glClearColor(color.r, color.g, color.b, color.a); + mask |= GL_COLOR_BUFFER_BIT; + } + if (clearDepth) mask |= GL_DEPTH_BUFFER_BIT; + glClear(mask); + } + + void OpenGLCommandBuffer::SetStencilFunc(const CompareOp compare, const uint32_t ref, const uint32_t mask) const + { + glStencilFunc(MapCompareOp(compare), ref, mask); + } + + void OpenGLCommandBuffer::SetLineSmooth(const bool enable) const + { + if (enable) glEnable(GL_LINE_SMOOTH); + else glDisable(GL_LINE_SMOOTH); + } + + void OpenGLCommandBuffer::SetDepthWrite(const bool enable) const + { + glDepthMask(enable ? GL_TRUE : GL_FALSE); + } + + void OpenGLCommandBuffer::CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, + uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, + uint32_t width, uint32_t height, uint32_t depth) const + { + glCopyImageSubData(srcTexture, GL_TEXTURE_CUBE_MAP, srcLevel, srcX, srcY, srcZ, + dstTexture, GL_TEXTURE_CUBE_MAP, dstLevel, dstX, dstY, dstZ, + width, height, depth); + } + + int32_t OpenGLCommandBuffer::GetUniformLocation(const uint32_t program, const std::string& name) const { + return glGetUniformLocation(program, name.c_str()); + } + + GLuint BlitMaskToOpenGL(BlitMask mask) + { + switch (mask) { + case BlitMask::Color: return GL_COLOR_BUFFER_BIT; + case BlitMask::Depth: return GL_DEPTH_BUFFER_BIT; + case BlitMask::Stencila: return GL_STENCIL_BUFFER_BIT; + } + return 0; + } + + GLuint BlitFilterToOpenGL(BlitFilter filter) + { + switch (filter) { + case BlitFilter::Nearest: return GL_NEAREST; + case BlitFilter::Linear: return GL_LINEAR; + } + return 0; + } + + void OpenGLCommandBuffer::BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0, + int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const + { + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, BlitMaskToOpenGL(mask), BlitFilterToOpenGL(filter)); + } + + void OpenGLCommandBuffer::ProgramUniform1f(const uint32_t program, const int32_t location, const float value) const + { + glProgramUniform1f(program, location, value); + } + + void OpenGLCommandBuffer::UseProgram(const uint32_t programID) const + { + glUseProgram(programID); + } + + void OpenGLCommandBuffer::BindStorageBuffer(const uint32_t binding, const Ref& ref) const + { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, ref->GetRendererID()); + } + + void OpenGLCommandBuffer::ResolveMultisampleTexture(const Ref& src, const Ref& dst) const + { + uint32_t resolveFBO; + glGenFramebuffers(1, &resolveFBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->GetRendererID(), 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, src->GetRendererID()); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, src->GetWidth(), src->GetHeight(), + 0, 0, src->GetWidth(), src->GetHeight(), + GL_COLOR_BUFFER_BIT, GL_LINEAR); + glDeleteFramebuffers(1, &resolveFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } +} diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h new file mode 100644 index 0000000..5646117 --- /dev/null +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h @@ -0,0 +1,97 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#ifndef PRISM_OPENGLCOMMANDBUFFER_H +#define PRISM_OPENGLCOMMANDBUFFER_H +#include "OpenGLRenderPass.h" +#include "glad/glad.h" +#include "Prism/Renderer/RHI/RHICommandBuffer.h" + +namespace Prism +{ + enum class TextureFormat; + + class OpenGLCommandBuffer : public RHICommandBuffer + { + public: + static GLenum MapCompareOp(CompareOp op); + + static GLenum MapStencilOp(StencilOp op); + + static GLenum MapCullMode(CullMode mode); + + static GLenum MapPolygonMode(PolygonMode mode); + + static GLenum MapPrimitiveType(PrimitiveType type); + + void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override; + + void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override; + + void SetDepthTest(bool enable) const override; + + void SetDepthFunc(CompareOp func) const override; + + void SetStencilTest(bool enable) const override; + + void SetStencilOp(StencilOp fail, StencilOp zFail, StencilOp zPass) const override; + + void SetStencilMask(uint32_t mask) const override; + + void SetCullMode(CullMode mode) const override; + + void SetPolygonMode(PolygonMode mode) const override; + + void SetLineWidth(float width) const override; + void SetLineThickness(float thickness) const override; + + void SetPointSize(float size) const override; + + void BindFramebuffer(RendererID rendererId) const override; + void BindFramebuffer(FramebufferTarget target, RendererID rendererId) const override; + void BindTexture(uint32_t slot, uint32_t textureID) const override; + void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const override; + void BindTextureUnit(uint32_t i, RendererID rendererId) const override; + void BindSampler(uint32_t slot, uint32_t samplerID) const override; + + void SetDrawBuffer(uint32_t attachment) const override; + void SetReadBuffer(uint32_t attachment) const override; + + void ClearBufferData(Ref buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const override; + + void GenerateMipmap(uint32_t textureID) const override; + + + void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const override; + + void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const override; + + void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const override; + + void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const override; + + void MemoryBarrier(MemoryBarrierMask barriers) const override; + + void Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const override; + void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override; + void SetLineSmooth(bool enable) const override; + void SetDepthWrite(bool enable) const override; + + void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, uint32_t width, uint32_t height, uint32_t depth) const override; + int32_t GetUniformLocation(uint32_t program, const std::string& name) const override; + void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const override; + + void ProgramUniform1f(uint32_t program, int32_t location, float value) const override; + + void UseProgram(uint32_t programID) const override; + + void BindStorageBuffer(uint32_t binding, const Ref& ref) const override; + + void ResolveMultisampleTexture(const Ref& src, const Ref& dst) const override; + + }; +} + + +#endif //PRISM_OPENGLCOMMANDBUFFER_H \ No newline at end of file diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp new file mode 100644 index 0000000..b3b6a56 --- /dev/null +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp @@ -0,0 +1,87 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#include "OpenGLRHIDevice.h" + +#include "OpenGLCommandBuffer.h" +#include "glm/gtc/type_ptr.hpp" + +#include "Prism/Renderer/RendererAPI.h" + +namespace Prism +{ + static GLenum MapFilterMode(FilterMode mode) { + switch (mode) { + case FilterMode::Nearest: return GL_NEAREST; + case FilterMode::Linear: return GL_LINEAR; + case FilterMode::NearestMipmapNearest: return GL_NEAREST_MIPMAP_NEAREST; + case FilterMode::LinearMipmapNearest: return GL_LINEAR_MIPMAP_NEAREST; + case FilterMode::NearestMipmapLinear: return GL_NEAREST_MIPMAP_LINEAR; + case FilterMode::LinearMipmapLinear: return GL_LINEAR_MIPMAP_LINEAR; + default: return GL_LINEAR; + } + } + + static GLenum MapWrapMode(WrapMode mode) { + switch (mode) { + case WrapMode::Repeat: return GL_REPEAT; + case WrapMode::MirroredRepeat: return GL_MIRRORED_REPEAT; + case WrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE; + case WrapMode::ClampToBorder: return GL_CLAMP_TO_BORDER; + case WrapMode::MirrorClampToEdge: return GL_MIRROR_CLAMP_TO_EDGE; + default: return GL_REPEAT; + } + } + + static GLenum MapCompareFunc(CompareFunc func) { + switch (func) { + case CompareFunc::Never: return GL_NEVER; + case CompareFunc::Less: return GL_LESS; + case CompareFunc::Equal: return GL_EQUAL; + case CompareFunc::LessEqual: return GL_LEQUAL; + case CompareFunc::Greater: return GL_GREATER; + case CompareFunc::NotEqual: return GL_NOTEQUAL; + case CompareFunc::GreaterEqual: return GL_GEQUAL; + case CompareFunc::Always: return GL_ALWAYS; + default: return GL_ALWAYS; + } + } + + + + Ref OpenGLRHIDevice::CreateCommandBuffer() + { + return Ref::Create(); + } + + RendererID OpenGLRHIDevice::CreateSampler(const SamplerDesc& desc) + { + GLuint sampler; + glGenSamplers(1, &sampler); + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, MapFilterMode(desc.MinFilter)); + glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, MapFilterMode(desc.MagFilter)); + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, MapWrapMode(desc.WrapU)); + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, MapWrapMode(desc.WrapV)); + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, MapWrapMode(desc.WrapW)); + if (desc.MaxAnisotropy > 1.0f) { + glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.MaxAnisotropy); + } + glSamplerParameterf(sampler, GL_TEXTURE_LOD_BIAS, desc.MipLodBias); + if (desc.EnableCompare) { + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, MapCompareFunc(desc.CompareFunc)); + } else { + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + if (desc.WrapU == WrapMode::ClampToBorder || desc.WrapV == WrapMode::ClampToBorder || desc.WrapW == WrapMode::ClampToBorder) { + glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(desc.BorderColor)); + } + return sampler; + } + + void OpenGLRHIDevice::DestroySampler(const RendererID sampler) + { + glDeleteSamplers(1, &sampler); + } +} diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h b/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h new file mode 100644 index 0000000..299e44b --- /dev/null +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h @@ -0,0 +1,22 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#ifndef PRISM_OPENGLRHIDEVICE_H +#define PRISM_OPENGLRHIDEVICE_H +#include "Prism/Renderer/RHI/RHIDevice.h" + +namespace Prism +{ + class OpenGLRHIDevice : public RHIDevice + { + public: + Ref CreateCommandBuffer() override; + + RendererID CreateSampler(const SamplerDesc& desc) override; + void DestroySampler(RendererID sampler) override; + }; +} + + +#endif //PRISM_OPENGLRHIDEVICE_H \ No newline at end of file diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp index 4393b02..4d71cd9 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -7,6 +7,7 @@ #include "glad/glad.h" #include "Prism/Core/Log.h" +#include "Prism/Renderer/RHI/RHICommandBuffer.h" namespace Prism { diff --git a/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp new file mode 100644 index 0000000..eba531d --- /dev/null +++ b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp @@ -0,0 +1,5 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#include "RHICommandBuffer.h" \ No newline at end of file diff --git a/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h new file mode 100644 index 0000000..baed574 --- /dev/null +++ b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h @@ -0,0 +1,123 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#ifndef PRISM_RHICOMMANDBUFFER_H +#define PRISM_RHICOMMANDBUFFER_H +#include "Prism/Core/Ref.h" +#include "Prism/Renderer/RendererAPI.h" + +#include + +namespace Prism { + class FrameBuffer; + class StorageBuffer; + enum class TextureFormat; + class Texture; + class IndexBuffer; + class VertexBuffer; + class Pipeline; + class RenderPass; + + enum class CompareOp { Never, Less, Equal, LessEqual, Greater, NotEqual, GreaterEqual, Always }; + enum class StencilOp { Keep, Zero, Replace, Incr, Decr, Invert, IncrWrap, DecrWrap }; + enum class CullMode { None, Front, Back }; + enum class PolygonMode { Fill, Line, Point }; + enum class PrimitiveType { Triangles, Lines, Points }; + enum class AccessMode { ReadOnly, WriteOnly, ReadWrite }; + enum class BufferFormat { R32UI, RGB16F }; + enum class PixelFormat { RED, RGBA }; + enum class BlitFilter { Nearest, Linear }; + enum class DataType { UnsignedInt }; + enum class BlitMask { Color, Depth, Stencila }; + + enum class MemoryBarrierMask { + None = 0, + VertexAttribArray, // GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT + ElementArray, // GL_ELEMENT_ARRAY_BARRIER_BIT + Uniform, // GL_UNIFORM_BARRIER_BIT + TextureFetch, // GL_TEXTURE_FETCH_BARRIER_BIT + ShaderImageAccess, // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT + Command, // GL_COMMAND_BARRIER_BIT + PixelBuffer, // GL_PIXEL_BUFFER_BARRIER_BIT + TextureUpdate, // GL_TEXTURE_UPDATE_BARRIER_BIT + BufferUpdate, // GL_BUFFER_UPDATE_BARRIER_BIT + Framebuffer, // GL_FRAMEBUFFER_BARRIER_BIT + TransformFeedback, // GL_TRANSFORM_FEEDBACK_BARRIER_BIT + AtomicCounter, // GL_ATOMIC_COUNTER_BARRIER_BIT + ShaderStorage, // GL_SHADER_STORAGE_BARRIER_BIT + All // GL_ALL_BARRIER_BITS + }; + + enum class FramebufferTarget {Read, Draw, Both}; + + class PRISM_API RHICommandBuffer : public RefCounted + { + public: + virtual ~RHICommandBuffer() = default; + + // 状态设置 + virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0; + virtual void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0; + virtual void SetDepthTest(bool enable) const = 0; + virtual void SetDepthFunc(CompareOp func) const = 0; + virtual void SetStencilTest(bool enable) const = 0; + virtual void SetStencilOp(StencilOp fail, StencilOp zfail, StencilOp zpass) const = 0; + virtual void SetStencilMask(uint32_t mask) const = 0; + virtual void SetCullMode(CullMode mode) const = 0; + virtual void SetPolygonMode(PolygonMode mode) const = 0; + virtual void SetLineWidth(float width) const = 0; + virtual void SetPointSize(float size) const = 0; + virtual void SetLineThickness(float thickness) const = 0; + + virtual void BindFramebuffer(uint32_t fbo) const = 0; + virtual void BindFramebuffer(FramebufferTarget target, uint32_t fbo) const = 0; + virtual void BindTexture(uint32_t slot, uint32_t textureID) const = 0; + virtual void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const = 0; + virtual void BindTextureUnit(uint32_t i, RendererID rendererId) const = 0; + virtual void BindSampler(uint32_t slot, uint32_t samplerID) const = 0; + + virtual void SetReadBuffer(uint32_t attachment) const = 0; + virtual void SetDrawBuffer(uint32_t attachment) const = 0; + + virtual void ClearBufferData(Ref buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const = 0; + + virtual void GenerateMipmap(uint32_t textureID) const = 0; + + // 绘制 + virtual void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const = 0; + virtual void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const = 0; + virtual void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, + uint32_t firstVertex, uint32_t firstInstance) const = 0; + + // 计算 + virtual void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const = 0; + virtual void MemoryBarrier(MemoryBarrierMask barriers) const = 0; + + virtual void Clear(const glm::vec4& color, bool clearColor = true, bool clearDepth = true) const = 0; + virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0; + virtual void SetLineSmooth(bool enable) const = 0; + virtual void SetDepthWrite(bool enable) const = 0; + + virtual void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, + uint32_t srcLevel, uint32_t dstLevel, + uint32_t srcX, uint32_t srcY, uint32_t srcZ, + uint32_t dstX, uint32_t dstY, uint32_t dstZ, + uint32_t width, uint32_t height, uint32_t depth) const = 0; + + virtual void ProgramUniform1f(uint32_t program, int32_t location, float value) const = 0; + virtual void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, + int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1, + BlitMask mask, BlitFilter filter) const = 0; + + virtual int32_t GetUniformLocation(uint32_t program, const std::string& name) const = 0; + + virtual void UseProgram(uint32_t programID) const = 0; + virtual void BindStorageBuffer(uint32_t binding, const Ref& ref) const = 0; + + virtual void ResolveMultisampleTexture(const Ref& src, const Ref& dst) const = 0; + }; + +} + +#endif //PRISM_RHICOMMANDBUFFER_H \ No newline at end of file diff --git a/Prism/src/Prism/Renderer/RHI/RHIDevice.cpp b/Prism/src/Prism/Renderer/RHI/RHIDevice.cpp new file mode 100644 index 0000000..5cee9de --- /dev/null +++ b/Prism/src/Prism/Renderer/RHI/RHIDevice.cpp @@ -0,0 +1,23 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#include "RHIDevice.h" + +#include "Prism/Platform/OpenGL/OpenGLRHIDevice.h" +#include "Prism/Renderer/RendererAPI.h" + + +namespace Prism +{ + Ref RHIDevice::Create() + { + switch (RendererAPI::Current()) + { + case RendererAPIType::None: return nullptr; + case RendererAPIType::OpenGL: return Ref::Create(); + } + + return nullptr; + } +} diff --git a/Prism/src/Prism/Renderer/RHI/RHIDevice.h b/Prism/src/Prism/Renderer/RHI/RHIDevice.h new file mode 100644 index 0000000..cd53968 --- /dev/null +++ b/Prism/src/Prism/Renderer/RHI/RHIDevice.h @@ -0,0 +1,95 @@ +// +// Created by Atdunbg on 2026/3/31. +// + +#ifndef PRISM_RHIDEVICE_H +#define PRISM_RHIDEVICE_H +#include "Prism/Core/Ref.h" +#include "Prism/Renderer/RendererAPI.h" +#include + +namespace Prism +{ + struct FramebufferSpecification; + struct RenderPassSpecification; + class RHICommandBuffer; + class StorageBuffer; + class RenderPass; + class FrameBuffer; + class Pipeline; + class Shader; + class Texture; + class IndexBuffer; + class VertexBuffer; + + struct BufferDesc { + uint32_t Size; + uint32_t Usage; // GL_STATIC_DRAW, GL_DYNAMIC_DRAW, etc. + // 对于 OpenGL,还需要 target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER) + uint32_t Target; + }; + + struct TextureDesc { + uint32_t Width, Height, Depth; + uint32_t MipLevels; + uint32_t Format; // GL_RGBA8, GL_RGBA16F, etc. + bool IsCubeMap = false; + bool IsArray = false; + uint32_t Layers = 1; + }; + + enum class FilterMode { + Nearest, // GL_NEAREST + Linear, // GL_LINEAR + NearestMipmapNearest, // GL_NEAREST_MIPMAP_NEAREST + LinearMipmapNearest, // GL_LINEAR_MIPMAP_NEAREST + NearestMipmapLinear, // GL_NEAREST_MIPMAP_LINEAR + LinearMipmapLinear // GL_LINEAR_MIPMAP_LINEAR + }; + + enum class WrapMode { + Repeat, // GL_REPEAT + MirroredRepeat, // GL_MIRRORED_REPEAT + ClampToEdge, // GL_CLAMP_TO_EDGE + ClampToBorder, // GL_CLAMP_TO_BORDER + MirrorClampToEdge // GL_MIRROR_CLAMP_TO_EDGE (可选) + }; + + enum class CompareFunc { + Never, // GL_NEVER + Less, // GL_LESS + Equal, // GL_EQUAL + LessEqual, // GL_LEQUAL + Greater, // GL_GREATER + NotEqual, // GL_NOTEQUAL + GreaterEqual, // GL_GEQUAL + Always // GL_ALWAYS + }; + + struct SamplerDesc { + FilterMode MinFilter = FilterMode::Linear; // 缩小过滤 + FilterMode MagFilter = FilterMode::Linear; // 放大过滤 + WrapMode WrapU = WrapMode::Repeat; // U 方向包裹模式 + WrapMode WrapV = WrapMode::Repeat; // V 方向包裹模式 + WrapMode WrapW = WrapMode::Repeat; // W 方向包裹模式(3D/数组纹理) + float MaxAnisotropy = 1.0f; // 各向异性过滤(1.0 表示禁用) + float MipLodBias = 0.0f; // Mipmap LOD 偏移 + CompareFunc CompareFunc = CompareFunc::Never; // 用于阴影比较的采样器 + bool EnableCompare = false; // 是否启用比较模式(阴影贴图) + glm::vec4 BorderColor = glm::vec4(0.0f); // ClampToBorder 时的边界颜色 + }; + + class PRISM_API RHIDevice : public RefCounted + { + public: + static Ref Create(); + + virtual ~RHIDevice() = default; + virtual Ref CreateCommandBuffer() = 0; + virtual RendererID CreateSampler(const SamplerDesc& desc) = 0; + virtual void DestroySampler(RendererID sampler) = 0; + }; +} + + +#endif //PRISM_RHIDEVICE_H \ No newline at end of file diff --git a/Prism/src/Prism/Renderer/Renderer.cpp b/Prism/src/Prism/Renderer/Renderer.cpp index 8d03405..b4e9627 100644 --- a/Prism/src/Prism/Renderer/Renderer.cpp +++ b/Prism/src/Prism/Renderer/Renderer.cpp @@ -9,11 +9,16 @@ #include "RendererAPI.h" #include "SceneRenderer.h" #include "glad/glad.h" +#include "RHI/RHICommandBuffer.h" +#include "RHI/RHIDevice.h" namespace Prism { RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL; + Ref Renderer::s_Device; + Ref Renderer::s_CommandBuffer; + struct RendererData { @@ -30,6 +35,9 @@ namespace Prism void Renderer::Init() { + s_Device = RHIDevice::Create(); + s_CommandBuffer = s_Device->CreateCommandBuffer(); + s_Data.m_ShaderLibrary = Ref::Create(); Submit([](){ RendererAPI::Init(); }); @@ -62,18 +70,30 @@ namespace Prism s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices)); } + Ref Renderer::GetCommandBuffer() + { + return s_CommandBuffer; + } + + Ref Renderer::GetDevice() + { + return s_Device; + } + void Renderer::Clear() { - Submit([]() + auto cmd = s_CommandBuffer; + Submit([cmd]() { - RendererAPI::Clear(0.0f, 0.0f, 0.0f, 1.0f); + cmd->Clear({0.0f, 0.0f, 0.0f, 1.0f}); }); } void Renderer::Clear(float r, float g, float b, float a) { - Submit([=](){ - RendererAPI::Clear(r, g, b, a); + auto cmd = s_CommandBuffer; + Submit([r, g, b, a, cmd](){ + cmd->Clear({r, g, b, a}); }); } @@ -90,15 +110,18 @@ namespace Prism void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace) { - Submit([=]() { - RendererAPI::DrawIndexed(count, type, depthTest, cullFace); + + auto cmd = s_CommandBuffer; + Submit([cmd, count, type, depthTest, cullFace]() { + cmd->DrawIndexed(count, type, depthTest, cullFace); }); } void Renderer::SetLineThickness(const float thickness) { - Submit([=]() { - RendererAPI::SetLineThickness(thickness); + auto cmd = s_CommandBuffer; + Submit([cmd, thickness]() { + cmd->SetLineThickness(thickness); }); } @@ -116,19 +139,25 @@ namespace Prism renderPass->GetSpecification().TargetFramebuffer->Bind(); - if (clear) - { - const glm::vec4& clearColor = renderPass->GetSpecification().TargetFramebuffer->GetSpecification().ClearColor; - Submit([=]() { - RendererAPI::Clear(clearColor.r, clearColor.g, clearColor.b, clearColor.a); - }); - } + auto cmd = s_CommandBuffer; + auto fb = renderPass->GetSpecification().TargetFramebuffer; + Submit([cmd, fb, clear]() { + cmd->BindFramebuffer(fb->GetRendererID()); + if (clear) + { + const glm::vec4& clearColor = fb->GetSpecification().ClearColor; + cmd->Clear(clearColor, true, true); + } + }); } void Renderer::EndRenderPass() { - PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass! Have you called Renderer::EndRenderPass twice?"); - s_Data.m_ActiveRenderPass->GetSpecification().TargetFramebuffer->Unbind(); + PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass!"); + auto cmd = s_CommandBuffer; + Submit([cmd]() { + cmd->BindFramebuffer(0); + }); s_Data.m_ActiveRenderPass = nullptr; } @@ -169,7 +198,7 @@ namespace Prism s_Data.m_FullscreenQuadPipeline->Bind(); s_Data.m_FullscreenQuadIndexBuffer->Bind(); - Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace); + DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace); } void Renderer::SubmitMesh(Ref& mesh, const glm::mat4& transform, const std::vector>& overrideMaterials) @@ -201,22 +230,15 @@ namespace Prism } shader->SetMat4("u_Transform", transform * submesh.Transform); - Renderer::Submit([submesh, material]() { - if (material->GetFlag(MaterialFlag::DepthTest)) - { - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - } - else - glDisable(GL_DEPTH_TEST); + auto cmd = s_CommandBuffer; + Submit([cmd, submesh, material]() { + // 状态设置通过 cmd + cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest)); + cmd->SetDepthFunc(CompareOp::LessEqual); // 对应 GL_LEQUAL + cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back); - if (!material->GetFlag(MaterialFlag::TwoSided)) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); - - - glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex); + // 绘制 + cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0); }); } } @@ -250,22 +272,12 @@ namespace Prism } shader->SetMat4("u_Transform", transform * submesh.Transform); - Renderer::Submit([submesh, material]() { - if (material->GetFlag(MaterialFlag::DepthTest)) - { - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - } - else - glDisable(GL_DEPTH_TEST); - - if (!material->GetFlag(MaterialFlag::TwoSided)) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); - - - glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex); + auto cmd = s_CommandBuffer; + Submit([cmd, submesh, material]() { + cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest)); + cmd->SetDepthFunc(CompareOp::LessEqual); + cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back); + cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0); }); } } @@ -289,8 +301,9 @@ namespace Prism } shader->SetMat4("u_Transform", transform * submesh.Transform); - Submit([submesh]() { - glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex); + auto cmd = s_CommandBuffer; + Submit([cmd, submesh]() { + cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0); }); } } @@ -335,19 +348,14 @@ namespace Prism void Renderer::DispatchCompute(int x, int y, int z) { - Submit([x, y, z]() + auto cmd = s_CommandBuffer; + Submit([x, y, z, cmd]() { - RendererAPI::DispatchCompute(x, y, z); + cmd->DispatchCompute(x, y, z); }); } - void Renderer::MemoryBarrier(int barrier) - { - Submit([barrier]() - { - RendererAPI::MemoryBarrier(barrier); - }); - } + RenderCommandQueue& Renderer::GetRenderCommandQueue() { diff --git a/Prism/src/Prism/Renderer/Renderer.h b/Prism/src/Prism/Renderer/Renderer.h index 0649dd6..9e0d766 100644 --- a/Prism/src/Prism/Renderer/Renderer.h +++ b/Prism/src/Prism/Renderer/Renderer.h @@ -13,12 +13,19 @@ namespace Prism { - class PRISM_API Renderer + enum class PrimitiveType; + class RHICommandBuffer; + class RHIDevice; + + class PRISM_API Renderer { public: typedef void(*RenderCommandFn)(void*); static void Init(); + static Ref GetCommandBuffer(); + static Ref GetDevice(); + static void Clear(); static void Clear(float r, float g, float b, float a = 1.0f); static void SetClearColor(float r, float g, float b, float a); @@ -61,10 +68,12 @@ namespace Prism static void DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f)); static void DrawAABB(const Ref& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f)); static void DispatchCompute(int x, int y, int z); - static void MemoryBarrier(int barrier); private: static RenderCommandQueue& GetRenderCommandQueue(); + + static Ref s_Device; + static Ref s_CommandBuffer; }; #if 0 diff --git a/Prism/src/Prism/Renderer/Renderer2D.cpp b/Prism/src/Prism/Renderer/Renderer2D.cpp index 6a3df24..1de072a 100644 --- a/Prism/src/Prism/Renderer/Renderer2D.cpp +++ b/Prism/src/Prism/Renderer/Renderer2D.cpp @@ -7,6 +7,7 @@ #include "Renderer.h" #include "Shader.h" #include "VertexArray.h" +#include "RHI/RHICommandBuffer.h" namespace Prism { diff --git a/Prism/src/Prism/Renderer/Renderer3D.cpp b/Prism/src/Prism/Renderer/Renderer3D.cpp index 03e60f7..77642d9 100644 --- a/Prism/src/Prism/Renderer/Renderer3D.cpp +++ b/Prism/src/Prism/Renderer/Renderer3D.cpp @@ -6,13 +6,15 @@ #include "Prism/Core/Timer.h" #include "Prism/Scene/Scene.h" -#include #include "Renderer.h" #include "Renderer2D.h" #include "SceneRenderer.h" #include "StorageBuffer.h" +#include "glad/glad.h" #include "Prism/Scene/Components.h" +#include "RHI/RHICommandBuffer.h" +#include "RHI/RHIDevice.h" namespace Prism { @@ -225,16 +227,14 @@ namespace Prism shadowMapRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(shadowMapFramebufferSpec); s_Data.ShadowMapRenderPass = RenderPass::Create(shadowMapRenderPassSpec); - Renderer::Submit([]() - { - glGenSamplers(1, &s_Data.ShadowMapSampler); + auto cmd = Renderer::GetCommandBuffer(); - // Setup the shadowMap depth sampler - glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - }); + SamplerDesc desc; + desc.MinFilter = FilterMode::Linear; + desc.MagFilter = FilterMode::Linear; + desc.WrapU = WrapMode::ClampToEdge; + desc.WrapV = WrapMode::ClampToEdge; + s_Data.ShadowMapSampler = Renderer::GetDevice()->CreateSampler(desc); } ///////////////////////////////////////////// @@ -340,6 +340,8 @@ namespace Prism constexpr uint32_t cubemapSize = 2048; constexpr uint32_t irradianceMapSize = 32; + auto cmd = Renderer::GetCommandBuffer(); + Ref envUnfiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize); if (!equirectangularConversionShader) equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl"); @@ -349,11 +351,11 @@ namespace Prism equirectangularConversionShader->Bind(); envEquirect->Bind(); - Renderer::Submit([envUnfiltered, cubemapSize, envEquirect]() + Renderer::Submit([envUnfiltered, cubemapSize, envEquirect, cmd]() { - glBindImageTexture(0, envUnfiltered->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F); - glDispatchCompute(cubemapSize / 32, cubemapSize / 32, 6); - glGenerateTextureMipmap(envUnfiltered->GetRendererID()); + cmd->BindImageTexture(0, envUnfiltered->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F); + cmd->DispatchCompute(cubemapSize / 32, cubemapSize / 32, 6); + cmd->GenerateMipmap(envUnfiltered->GetRendererID()); }); @@ -362,24 +364,26 @@ namespace Prism Ref envFiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize); - Renderer::Submit([envUnfiltered, envFiltered]() + Renderer::Submit([envUnfiltered, envFiltered, cmd]() { - glCopyImageSubData(envUnfiltered->GetRendererID(), GL_TEXTURE_CUBE_MAP, 0, 0, 0, 0, - envFiltered->GetRendererID(), GL_TEXTURE_CUBE_MAP, 0, 0, 0, 0, - envFiltered->GetWidth(), envFiltered->GetHeight(), 6); + cmd->CopyImageSubData(envUnfiltered->GetRendererID(), envFiltered->GetRendererID(), + 0, 0, 0, 0, 0, 0, 0, 0, + envFiltered->GetWidth(), envFiltered->GetHeight(), 6); }); envFilteringShader->Bind(); envUnfiltered->Bind(); - Renderer::Submit([envUnfiltered, envFiltered, cubemapSize]() { + Renderer::Submit([envUnfiltered, envFiltered, cubemapSize, cmd]() { const float deltaRoughness = 1.0f / glm::max((float)(envFiltered->GetMipLevelCount() - 1.0f), 1.0f); for (int level = 1, size = cubemapSize / 2; level < (int)envFiltered->GetMipLevelCount(); level++, size /= 2) // <= ? { - const GLuint numGroups = glm::max(1, size / 32); - glBindImageTexture(0, envFiltered->GetRendererID(), level, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F); - glProgramUniform1f(envFilteringShader->GetRendererID(), 0, level * deltaRoughness); - glDispatchCompute(numGroups, numGroups, 6); + const uint32_t numGroups = glm::max(1, size / 32); + cmd->BindImageTexture(0, envFiltered->GetRendererID(), level, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F); + // 设置 uniform(这里假设 uniform 位置 0 是 roughness) + cmd->ProgramUniform1f(envFilteringShader->GetRendererID(), 0, level * deltaRoughness); + cmd->DispatchCompute(numGroups, numGroups, 6); + cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess); } }); @@ -389,11 +393,12 @@ namespace Prism Ref irradianceMap = TextureCube::Create(TextureFormat::RGBA16F, irradianceMapSize, irradianceMapSize); envIrradianceShader->Bind(); envFiltered->Bind(); - Renderer::Submit([irradianceMap]() + Renderer::Submit([irradianceMap, cmd]() { - glBindImageTexture(0, irradianceMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F); - glDispatchCompute(irradianceMap->GetWidth() / 32, irradianceMap->GetHeight() / 32, 6); - glGenerateTextureMipmap(irradianceMap->GetRendererID()); + cmd->BindImageTexture(0, irradianceMap->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F); + cmd->DispatchCompute(irradianceMap->GetWidth() / 32, irradianceMap->GetHeight() / 32, 6); + cmd->GenerateMipmap(irradianceMap->GetRendererID()); + cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess); }); return { envFiltered, irradianceMap }; @@ -405,6 +410,7 @@ namespace Prism Ref Renderer3D::CreatePreethamSky(const glm::vec3& turbidityAzimuthInclination) { constexpr uint32_t cubemapSize = 2048; + auto cmd = Renderer::GetCommandBuffer(); Ref environmentMap = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize); @@ -415,12 +421,13 @@ namespace Prism preethamSkyShader->SetFloat3("u_TurbidityAzimuthInclination", turbidityAzimuthInclination); - Renderer::Submit([environmentMap, cubemapSize]() + + Renderer::Submit([environmentMap, cubemapSize, cmd]() { - glBindImageTexture(0, environmentMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F); - glDispatchCompute(cubemapSize / 32, cubemapSize / 32, 6); - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - glGenerateTextureMipmap(environmentMap->GetRendererID()); + cmd->BindImageTexture(0, environmentMap->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F); + cmd->DispatchCompute(cubemapSize / 32, cubemapSize / 32, 6); + cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess); + cmd->GenerateMipmap(environmentMap->GetRendererID()); }); return environmentMap; @@ -513,64 +520,69 @@ namespace Prism float dt = ae.ExposureTimer; ae.ExposureTimer.Reset(); - Renderer::Submit([srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO]() { - glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID()); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - 0, 0, dstFB->GetWidth(), dstFB->GetHeight(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + auto cmd = Renderer::GetCommandBuffer(); - const uint32_t zero = 0; - glClearNamedBufferData(histSSBO->GetRendererID(), GL_R32UI, GL_RED, GL_UNSIGNED_INT, &zero); + Renderer::Submit([cmd, srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO, ae, dt]() { + cmd->BindFramebuffer(FramebufferTarget::Read, srcFB->GetRendererID()); + cmd->BindFramebuffer(FramebufferTarget::Draw, dstFB->GetRendererID()); - glUseProgram(histCS->GetRendererID()); - glBindTextureUnit(0, dstFB->GetColorAttachmentRendererID()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, histSSBO->GetRendererID()); + cmd->SetReadBuffer(0); + cmd->SetDrawBuffer(0); - const GLint locLogMin = glGetUniformLocation(histCS->GetRendererID(), "u_LogMin"); - const GLint locLogMax = glGetUniformLocation(histCS->GetRendererID(), "u_LogMax"); - if (locLogMin != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMin, logMin); - if (locLogMax != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMax, logMax); + cmd->BlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), 0, 0, dstFB->GetWidth(), dstFB->GetHeight(),BlitMask::Color, BlitFilter::Nearest); - const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16; - const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16; - glDispatchCompute(groupsX, groupsY, 1); - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - }); + cmd->BindFramebuffer(FramebufferTarget::Read, 0); + cmd->BindFramebuffer(FramebufferTarget::Draw, 0); - Renderer::Submit([&ae, dt]() { - glUseProgram(ae.ExposureCS->GetRendererID()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ae.HistogramSSBO->GetRendererID()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ae.ExposureSSBO->GetRendererID()); + constexpr uint32_t zero = 0; + cmd->ClearBufferData(histSSBO, BufferFormat::R32UI, PixelFormat::RED, DataType::UnsignedInt, &zero); - auto setUniform = [&](const char* name, const float value) { - const GLint loc = glGetUniformLocation(ae.ExposureCS->GetRendererID(), name); - if (loc != -1) glProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value); - }; + cmd->UseProgram(histCS->GetRendererID()); - setUniform("u_SpeedUp", ae.SpeedUp); - setUniform("u_SpeedDown", ae.SpeedDown); - setUniform("u_Key", ae.Key); - setUniform("u_LowPercent", ae.LowPercent); - setUniform("u_HighPercent", ae.HighPercent); - setUniform("u_MinExposure", ae.MinExposure); - setUniform("u_MaxExposure", ae.MaxExposure); - setUniform("u_DeltaTime", dt); - setUniform("u_LogMin", ae.LogMin); - setUniform("u_LogMax", ae.LogMax); + cmd->BindTextureUnit(0, dstFB->GetColorAttachmentRendererID()); + cmd->BindStorageBuffer(1, histSSBO); - glDispatchCompute(1, 1, 1); - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - }); + + + int32_t logMinLoc = cmd->GetUniformLocation(histCS->GetRendererID(), "u_LogMin"); + int32_t logMaxLoc = cmd->GetUniformLocation(histCS->GetRendererID(), "u_LogMax"); + if (logMinLoc != -1) cmd->ProgramUniform1f(histCS->GetRendererID(), logMinLoc, logMin); + if (logMaxLoc != -1) cmd->ProgramUniform1f(histCS->GetRendererID(), logMaxLoc, logMax); + + const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16; + const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16; + cmd->DispatchCompute(groupsX, groupsY, 1); + cmd->MemoryBarrier(MemoryBarrierMask::ShaderStorage); + + cmd->UseProgram(ae.ExposureCS->GetRendererID()); + cmd->BindStorageBuffer(0, ae.HistogramSSBO); + cmd->BindStorageBuffer(1, ae.ExposureSSBO); + + auto setUniform = [&](const char* name, const float value) { + const int32_t loc = cmd->GetUniformLocation(ae.ExposureCS->GetRendererID(), name); + if (loc != -1) cmd->ProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value); + }; + + setUniform("u_SpeedUp", ae.SpeedUp); + setUniform("u_SpeedDown", ae.SpeedDown); + setUniform("u_Key", ae.Key); + setUniform("u_LowPercent", ae.LowPercent); + setUniform("u_HighPercent", ae.HighPercent); + setUniform("u_MinExposure", ae.MinExposure); + setUniform("u_MaxExposure", ae.MaxExposure); + setUniform("u_DeltaTime", dt); + setUniform("u_LogMin", ae.LogMin); + setUniform("u_LogMax", ae.LogMax); + + cmd->DispatchCompute(1, 1, 1); + cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess); + }); } void Renderer3D::ShadowMapPass() { const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights; + auto cmd = Renderer::GetCommandBuffer(); if (!s_Data.ShadowEnabled || directionalLights[0].Intensity == 0.0f || !directionalLights[0].CastShadows) { // Clear shadow maps @@ -589,10 +601,10 @@ namespace Prism const glm::mat4 lightProjection = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, nearPlane, farPlane); const glm::mat4 lightSpaceMatrix = lightProjection * lightView; - Renderer::Submit([]() + // auto cmd = Renderer::GetCommandBuffer(); + Renderer::Submit([cmd]() { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + cmd->SetCullMode(CullMode::Back); }); { @@ -617,12 +629,16 @@ namespace Prism { const bool outline = !s_Data.SelectedMeshDrawList.empty(); const bool collider = !s_Data.ColliderDrawList.empty(); + auto cmd = Renderer::GetCommandBuffer(); if (outline) { - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + cmd->SetStencilTest(true); // 开启模板测试 + cmd->SetStencilOp(StencilOp::Replace, StencilOp::Replace, StencilOp::Replace); + cmd->SetStencilFunc(CompareOp::Always, 1, 0xFF); // 总是通过,写入参考值1 + cmd->SetStencilMask(0xFF); }); } @@ -630,9 +646,9 @@ namespace Prism if (outline) { - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glStencilMask(0); + cmd->SetStencilMask(0); }); } @@ -689,24 +705,27 @@ namespace Prism auto reg = rd->GetRegister(); auto tex = s_Data.ShadowMapRenderPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID(); - Renderer::Submit([reg, tex]() mutable + Renderer::Submit([reg, tex, cmd]() mutable { - glBindTextureUnit(reg, tex); - glBindSampler(reg++, s_Data.ShadowMapSampler); + cmd->BindTextureUnit(reg, tex); + cmd->BindSampler(reg, s_Data.ShadowMapSampler); }); } Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.MaterialInstances); } + // TODO: bug outline is not correct + /* if (outline) { - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilMask(0xff); + cmd->SetStencilFunc(CompareOp::Always, 1, 0xff); + cmd->SetStencilMask(0xFF); }); } + */ for (auto& dc : s_Data.SelectedMeshDrawList) { auto baseMaterial = dc.mesh->GetMaterial(); @@ -756,15 +775,14 @@ namespace Prism if (outline) { - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glStencilFunc(GL_NOTEQUAL, 1, 0xff); - glStencilMask(0); - - glLineWidth(10); - glEnable(GL_LINE_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glDisable(GL_DEPTH_TEST); + cmd->SetStencilTest(true); // 确保模板测试开启 + cmd->SetStencilFunc(CompareOp::NotEqual, 1, 0xff); + cmd->SetStencilMask(0); + cmd->SetLineWidth(10); + cmd->SetPolygonMode(PolygonMode::Line); + cmd->SetDepthTest(false); }); // Draw outline here @@ -776,10 +794,10 @@ namespace Prism Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial); } - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glPointSize(10); - glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + cmd->SetPointSize(10); + cmd->SetPolygonMode(PolygonMode::Point); }); for (auto& dc : s_Data.SelectedMeshDrawList) { @@ -787,23 +805,24 @@ namespace Prism Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial); } - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glStencilMask(0xff); - glStencilFunc(GL_ALWAYS, 1, 0xff); - glEnable(GL_DEPTH_TEST); + cmd->SetPolygonMode(PolygonMode::Fill); + cmd->SetStencilMask(0xff); + cmd->SetStencilFunc(CompareOp::Always, 1, 0xff); + cmd->SetDepthTest(true); + cmd->SetStencilTest(false); }); } if (collider) { - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glLineWidth(1); - glEnable(GL_LINE_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glDisable(GL_DEPTH_TEST); + cmd->SetLineWidth(1); + cmd->SetLineSmooth(true); + cmd->SetPolygonMode(PolygonMode::Line); + cmd->SetDepthTest(false); }); s_Data.ColliderMaterial->Set("u_ViewProjection", cameraViewProjection); @@ -813,10 +832,10 @@ namespace Prism Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial); } - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glPointSize(1); - glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + cmd->SetPointSize(1); + cmd->SetPolygonMode(PolygonMode::Point); }); for (auto& dc : s_Data.ColliderDrawList) @@ -825,10 +844,10 @@ namespace Prism Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial); } - Renderer::Submit([]() + Renderer::Submit([cmd]() { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_DEPTH_TEST); + cmd->SetPolygonMode(PolygonMode::Fill); + cmd->SetDepthTest(true); }); } @@ -906,11 +925,12 @@ namespace Prism void Renderer3D::GridPass() { Renderer::BeginRenderPass(s_Data.GeoPass, false); + auto cmd = Renderer::GetCommandBuffer(); if (const auto option = GetOptions(); option.ShowGrid) { - Renderer::Submit([]() { - glDepthMask(GL_FALSE); + Renderer::Submit([cmd]() { + cmd->SetDepthWrite(false); }); const auto& sceneCamera = s_Data.SceneData.SceneCamera; @@ -933,43 +953,27 @@ namespace Prism Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial); - Renderer::Submit([]() { - glDepthMask(GL_TRUE); + Renderer::Submit([cmd]() { + cmd->SetDepthWrite(true); }); } Renderer::EndRenderPass(); } - void CopyDepthBuffer(Ref src, Ref dst) - { - uint32_t srcID = src->GetRendererID(); // 假设 FrameBuffer 有此方法 - uint32_t dstID = dst->GetRendererID(); - - int srcWidth = src->GetWidth(); - int srcHeight = src->GetHeight(); - int dstWidth = dst->GetWidth(); - int dstHeight = dst->GetHeight(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, srcID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstID); - glBlitFramebuffer(0, 0, srcWidth, srcHeight, 0, 0, dstWidth, dstHeight, - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, 0); // 可选恢复 - } - void Renderer3D::CompositePass(const Ref& outRenderPass) { - + auto cmd = Renderer::GetCommandBuffer(); Renderer::Submit([srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer, - dstFB = outRenderPass->GetSpecification().TargetFramebuffer]() + dstFB = outRenderPass->GetSpecification().TargetFramebuffer, cmd]() { - glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID()); - glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - 0, 0, dstFB->GetWidth(), dstFB->GetHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + cmd->BindFramebuffer(FramebufferTarget::Read, srcFB->GetRendererID()); + cmd->BindFramebuffer(FramebufferTarget::Draw, dstFB->GetRendererID()); + cmd->BlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), + 0, 0, dstFB->GetWidth(), dstFB->GetHeight(), + BlitMask::Depth, BlitFilter::Nearest); + + cmd->BindFramebuffer(0); }); Renderer::BeginRenderPass(outRenderPass); @@ -1036,22 +1040,9 @@ namespace Prism s_Data.ResolvedHDRTexture = Texture2D::Create(TextureFormat::RGBA16F, width, height); } - Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture]() { - GLuint resolveFBO; - glGenFramebuffers(1, &resolveFBO); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolvedTex->GetRendererID(), 0); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID()); - glReadBuffer(GL_COLOR_ATTACHMENT0); - - glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - 0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - glDeleteFramebuffers(1, &resolveFBO); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + auto cmd = Renderer::GetCommandBuffer(); + Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture, cmd]() { + cmd->ResolveMultisampleTexture(srcFB, resolvedTex); }); } @@ -1178,3 +1169,4 @@ namespace Prism } } + diff --git a/Prism/src/Prism/Renderer/RendererAPI.h b/Prism/src/Prism/Renderer/RendererAPI.h index e27f291..43b7d07 100644 --- a/Prism/src/Prism/Renderer/RendererAPI.h +++ b/Prism/src/Prism/Renderer/RendererAPI.h @@ -7,6 +7,7 @@ namespace Prism { + enum class PrimitiveType; using RendererID = unsigned int; @@ -16,12 +17,6 @@ namespace Prism OpenGL }; - // TODO: move into separate header - enum class PrimitiveType - { - None = 0, Triangles, Lines - }; - struct RenderAPICapabilities { std::string Vendor;