894 lines
32 KiB
C++
894 lines
32 KiB
C++
#include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLEnums.h"
|
|
#include <algorithm>
|
|
#include <glad/glad.h>
|
|
|
|
#ifdef MemoryBarrier
|
|
#undef MemoryBarrier
|
|
#endif
|
|
|
|
namespace XCEngine {
|
|
namespace RHI {
|
|
|
|
namespace {
|
|
|
|
struct OpenGLVertexAttribFormat {
|
|
GLint componentCount = 0;
|
|
GLenum type = GL_FLOAT;
|
|
GLboolean normalized = GL_FALSE;
|
|
bool integer = false;
|
|
};
|
|
|
|
bool GetOpenGLVertexAttribFormat(Format format, OpenGLVertexAttribFormat& attributeFormat) {
|
|
switch (format) {
|
|
case Format::R8_UNorm:
|
|
attributeFormat = { 1, GL_UNSIGNED_BYTE, GL_TRUE, false };
|
|
return true;
|
|
case Format::R8G8_UNorm:
|
|
attributeFormat = { 2, GL_UNSIGNED_BYTE, GL_TRUE, false };
|
|
return true;
|
|
case Format::R8G8B8A8_UNorm:
|
|
attributeFormat = { 4, GL_UNSIGNED_BYTE, GL_TRUE, false };
|
|
return true;
|
|
case Format::R16_Float:
|
|
attributeFormat = { 1, GL_HALF_FLOAT, GL_FALSE, false };
|
|
return true;
|
|
case Format::R16G16B16A16_Float:
|
|
attributeFormat = { 4, GL_HALF_FLOAT, GL_FALSE, false };
|
|
return true;
|
|
case Format::R32_Float:
|
|
attributeFormat = { 1, GL_FLOAT, GL_FALSE, false };
|
|
return true;
|
|
case Format::R32G32_Float:
|
|
attributeFormat = { 2, GL_FLOAT, GL_FALSE, false };
|
|
return true;
|
|
case Format::R32G32B32A32_Float:
|
|
attributeFormat = { 4, GL_FLOAT, GL_FALSE, false };
|
|
return true;
|
|
case Format::R32_UInt:
|
|
attributeFormat = { 1, GL_UNSIGNED_INT, GL_FALSE, true };
|
|
return true;
|
|
case Format::R32G32B32A32_UInt:
|
|
attributeFormat = { 4, GL_UNSIGNED_INT, GL_FALSE, true };
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
OpenGLCommandList::OpenGLCommandList()
|
|
: m_primitiveType(GL_TRIANGLES)
|
|
, m_currentVAO(0)
|
|
, m_currentProgram(0)
|
|
, m_internalVAO(0)
|
|
, m_currentPipelineState(nullptr)
|
|
, m_currentShader(nullptr)
|
|
, m_composedFramebuffer(nullptr) {
|
|
}
|
|
|
|
OpenGLCommandList::~OpenGLCommandList() {
|
|
}
|
|
|
|
void OpenGLCommandList::Clear(float r, float g, float b, float a, unsigned int buffers) {
|
|
glClearColor(r, g, b, a);
|
|
glClear(ToOpenGLClearBuffer(buffers));
|
|
}
|
|
|
|
void OpenGLCommandList::ClearColor(float r, float g, float b, float a) {
|
|
glClearColor(r, g, b, a);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
void OpenGLCommandList::ClearDepth(float depth) {
|
|
glClearDepth(depth);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
void OpenGLCommandList::ClearStencil(int stencil) {
|
|
glClearStencil(stencil);
|
|
glClear(GL_STENCIL_BUFFER_BIT);
|
|
}
|
|
|
|
void OpenGLCommandList::ClearDepthStencil(float depth, int stencil) {
|
|
glClearDepth(depth);
|
|
glClearStencil(stencil);
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
}
|
|
|
|
void OpenGLCommandList::SetVertexBuffer(unsigned int buffer, size_t offset, size_t stride) {
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
|
glVertexAttribPointer(0, stride / sizeof(float), GL_FLOAT, GL_FALSE, stride, (void*)offset);
|
|
glEnableVertexAttribArray(0);
|
|
}
|
|
|
|
void OpenGLCommandList::SetVertexBuffers(unsigned int startSlot, unsigned int count, const unsigned int* buffers, const size_t* offsets, const size_t* strides) {
|
|
for (unsigned int i = 0; i < count; i++) {
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffers[i]);
|
|
glEnableVertexAttribArray(startSlot + i);
|
|
glVertexAttribPointer(startSlot + i, strides[i] / sizeof(float), GL_FLOAT, GL_FALSE, strides[i], (void*)offsets[i]);
|
|
}
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void OpenGLCommandList::SetIndexBuffer(unsigned int buffer, unsigned int type) {
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
|
}
|
|
|
|
void OpenGLCommandList::SetIndexBuffer(unsigned int buffer, unsigned int type, size_t offset) {
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
|
(void)offset;
|
|
}
|
|
|
|
void OpenGLCommandList::BindVertexArray(unsigned int vao) {
|
|
m_currentVAO = vao;
|
|
glBindVertexArray(vao);
|
|
}
|
|
|
|
void OpenGLCommandList::BindVertexArray(unsigned int vao, unsigned int indexBuffer, unsigned int indexType) {
|
|
m_currentVAO = vao;
|
|
glBindVertexArray(vao);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
(void)indexType;
|
|
}
|
|
|
|
void OpenGLCommandList::UseShader(unsigned int program) {
|
|
m_currentProgram = program;
|
|
glUseProgram(program);
|
|
}
|
|
|
|
void OpenGLCommandList::SetViewport(int x, int y, int width, int height) {
|
|
glViewport(x, y, width, height);
|
|
}
|
|
|
|
void OpenGLCommandList::SetViewport(float x, float y, float width, float height, float minDepth, float maxDepth) {
|
|
glViewportIndexedf(0, x, y, width, height);
|
|
glDepthRange(minDepth, maxDepth);
|
|
}
|
|
|
|
void OpenGLCommandList::SetViewports(unsigned int count, const float* viewports) {
|
|
for (unsigned int i = 0; i < count; i++) {
|
|
glViewportIndexedf(i, viewports[i * 6 + 0], viewports[i * 6 + 1], viewports[i * 6 + 2], viewports[i * 6 + 3]);
|
|
glDepthRangeIndexed(i, viewports[i * 6 + 4], viewports[i * 6 + 5]);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetScissor(int x, int y, int width, int height) {
|
|
glScissor(x, y, width, height);
|
|
}
|
|
|
|
void OpenGLCommandList::SetScissorRects(unsigned int count, const int* rects) {
|
|
for (unsigned int i = 0; i < count; i++) {
|
|
glScissorIndexed(i, rects[i * 4 + 0], rects[i * 4 + 1], rects[i * 4 + 2], rects[i * 4 + 3]);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::EnableScissorTest(bool enable) {
|
|
if (enable) glEnable(GL_SCISSOR_TEST);
|
|
else glDisable(GL_SCISSOR_TEST);
|
|
}
|
|
|
|
void OpenGLCommandList::EnableDepthTest(bool enable) {
|
|
if (enable) glEnable(GL_DEPTH_TEST);
|
|
else glDisable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
void OpenGLCommandList::EnableDepthWrite(bool enable) {
|
|
glDepthMask(enable ? GL_TRUE : GL_FALSE);
|
|
}
|
|
|
|
void OpenGLCommandList::SetDepthFunc(unsigned int func) {
|
|
glDepthFunc(func);
|
|
}
|
|
|
|
void OpenGLCommandList::EnableStencilTest(bool enable) {
|
|
if (enable) glEnable(GL_STENCIL_TEST);
|
|
else glDisable(GL_STENCIL_TEST);
|
|
}
|
|
|
|
void OpenGLCommandList::SetStencilFunc(unsigned int func, int ref, unsigned int mask) {
|
|
glStencilFunc(func, ref, mask);
|
|
}
|
|
|
|
void OpenGLCommandList::SetStencilOp(unsigned int fail, unsigned int zfail, unsigned int zpass) {
|
|
glStencilOp(fail, zfail, zpass);
|
|
}
|
|
|
|
void OpenGLCommandList::EnableBlending(bool enable) {
|
|
if (enable) glEnable(GL_BLEND);
|
|
else glDisable(GL_BLEND);
|
|
}
|
|
|
|
void OpenGLCommandList::SetBlendFunc(unsigned int src, unsigned int dst) {
|
|
glBlendFunc(src, dst);
|
|
}
|
|
|
|
void OpenGLCommandList::SetBlendFuncSeparate(unsigned int srcRGB, unsigned int dstRGB, unsigned int srcAlpha, unsigned int dstAlpha) {
|
|
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
|
}
|
|
|
|
void OpenGLCommandList::SetBlendEquation(unsigned int mode) {
|
|
glBlendEquation(mode);
|
|
}
|
|
|
|
void OpenGLCommandList::SetBlendColor(float r, float g, float b, float a) {
|
|
glBlendColor(r, g, b, a);
|
|
}
|
|
|
|
void OpenGLCommandList::EnableCulling(bool enable) {
|
|
if (enable) glEnable(GL_CULL_FACE);
|
|
else glDisable(GL_CULL_FACE);
|
|
}
|
|
|
|
void OpenGLCommandList::SetCullFace(unsigned int face) {
|
|
glCullFace(face);
|
|
}
|
|
|
|
void OpenGLCommandList::SetFrontFace(unsigned int face) {
|
|
glFrontFace(face);
|
|
}
|
|
|
|
void OpenGLCommandList::SetPolygonMode(unsigned int mode) {
|
|
glPolygonMode(GL_FRONT_AND_BACK, mode);
|
|
}
|
|
|
|
void OpenGLCommandList::SetPolygonOffset(float factor, float units) {
|
|
glPolygonOffset(factor, units);
|
|
}
|
|
|
|
void OpenGLCommandList::SetPrimitiveType(PrimitiveType type) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
}
|
|
|
|
void OpenGLCommandList::Draw(PrimitiveType type, unsigned int vertexCount, unsigned int startVertex) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glDrawArrays(m_primitiveType, startVertex, vertexCount);
|
|
}
|
|
|
|
void OpenGLCommandList::DrawInstanced(PrimitiveType type, unsigned int vertexCount, unsigned int instanceCount, unsigned int startVertex, unsigned int startInstance) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glDrawArraysInstanced(m_primitiveType, startVertex, vertexCount, instanceCount);
|
|
(void)startInstance;
|
|
}
|
|
|
|
void OpenGLCommandList::DrawIndexed(PrimitiveType type, unsigned int indexCount, unsigned int startIndex, int baseVertex) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glDrawElements(m_primitiveType, indexCount, GL_UNSIGNED_INT, (void*)(startIndex * sizeof(unsigned int)));
|
|
(void)baseVertex;
|
|
}
|
|
|
|
void OpenGLCommandList::DrawIndexedInstanced(PrimitiveType type, unsigned int indexCount, unsigned int instanceCount, unsigned int startIndex, int baseVertex, unsigned int startInstance) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glDrawElementsInstanced(m_primitiveType, indexCount, GL_UNSIGNED_INT, (void*)(startIndex * sizeof(unsigned int)), instanceCount);
|
|
(void)baseVertex;
|
|
(void)startInstance;
|
|
}
|
|
|
|
void OpenGLCommandList::DrawIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
|
|
glDrawArraysIndirect(m_primitiveType, (void*)offset);
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
|
|
(void)drawCount;
|
|
(void)stride;
|
|
}
|
|
|
|
void OpenGLCommandList::DrawIndexedIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
|
|
glDrawElementsIndirect(m_primitiveType, GL_UNSIGNED_INT, (void*)offset);
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
|
|
(void)drawCount;
|
|
(void)stride;
|
|
}
|
|
|
|
void OpenGLCommandList::MultiDrawArrays(PrimitiveType type, const int* first, const int* count, unsigned int drawCount) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glMultiDrawArrays(m_primitiveType, first, count, drawCount);
|
|
}
|
|
|
|
void OpenGLCommandList::MultiDrawElements(PrimitiveType type, const int* count, unsigned int type_, const void* const* indices, unsigned int drawCount) {
|
|
m_primitiveType = ToOpenGL(type);
|
|
glMultiDrawElements(m_primitiveType, count, type_, indices, drawCount);
|
|
}
|
|
|
|
void OpenGLCommandList::Dispatch(unsigned int x, unsigned int y, unsigned int z) {
|
|
glDispatchCompute(x, y, z);
|
|
}
|
|
|
|
void OpenGLCommandList::DispatchIndirect(unsigned int buffer, size_t offset) {
|
|
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
|
|
glDispatchComputeIndirect((GLintptr)offset);
|
|
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
|
|
}
|
|
|
|
void OpenGLCommandList::DispatchCompute(unsigned int x, unsigned int y, unsigned int z) {
|
|
glDispatchCompute(x, y, z);
|
|
}
|
|
|
|
void OpenGLCommandList::MemoryBarrier(unsigned int barriers) {
|
|
glMemoryBarrier(barriers);
|
|
}
|
|
|
|
void OpenGLCommandList::TextureBarrier() {
|
|
glTextureBarrier();
|
|
}
|
|
|
|
void OpenGLCommandList::BindTexture(unsigned int target, unsigned int unit, unsigned int texture) {
|
|
glActiveTexture(GL_TEXTURE0 + unit);
|
|
glBindTexture(target, texture);
|
|
}
|
|
|
|
void OpenGLCommandList::BindTextures(unsigned int first, unsigned int count, const unsigned int* textures) {
|
|
glBindTextures(first, count, textures);
|
|
}
|
|
|
|
void OpenGLCommandList::BindSampler(unsigned int unit, unsigned int sampler) {
|
|
glBindSampler(unit, sampler);
|
|
}
|
|
|
|
void OpenGLCommandList::BindSamplers(unsigned int first, unsigned int count, const unsigned int* samplers) {
|
|
glBindSamplers(first, count, samplers);
|
|
}
|
|
|
|
void OpenGLCommandList::BindImageTexture(unsigned int unit, unsigned int texture, int level, bool layered, int layer, unsigned int access, unsigned int format) {
|
|
glBindImageTexture(unit, texture, level, layered ? GL_TRUE : GL_FALSE, layer, access, format);
|
|
}
|
|
|
|
void OpenGLCommandList::BindBufferBase(unsigned int target, unsigned int index, unsigned int buffer) {
|
|
glBindBufferBase(target, index, buffer);
|
|
}
|
|
|
|
void OpenGLCommandList::BindBufferRange(unsigned int target, unsigned int index, unsigned int buffer, size_t offset, size_t size) {
|
|
glBindBufferRange(target, index, buffer, offset, size);
|
|
}
|
|
|
|
void OpenGLCommandList::Enable(unsigned int cap) {
|
|
glEnable(cap);
|
|
}
|
|
|
|
void OpenGLCommandList::Disable(unsigned int cap) {
|
|
glDisable(cap);
|
|
}
|
|
|
|
void OpenGLCommandList::Enablei(unsigned int cap, unsigned int index) {
|
|
glEnablei(cap, index);
|
|
}
|
|
|
|
void OpenGLCommandList::Disablei(unsigned int cap, unsigned int index) {
|
|
glDisablei(cap, index);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform1i(int location, int v) {
|
|
glUniform1i(location, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform1f(int location, float v) {
|
|
glUniform1f(location, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform2f(int location, float x, float y) {
|
|
glUniform2f(location, x, y);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform3f(int location, float x, float y, float z) {
|
|
glUniform3f(location, x, y, z);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform4f(int location, float x, float y, float z, float w) {
|
|
glUniform4f(location, x, y, z, w);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform1fv(int location, int count, const float* v) {
|
|
glUniform1fv(location, count, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform2fv(int location, int count, const float* v) {
|
|
glUniform2fv(location, count, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform3fv(int location, int count, const float* v) {
|
|
glUniform3fv(location, count, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniform4fv(int location, int count, const float* v) {
|
|
glUniform4fv(location, count, v);
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformMatrix4fv(int location, int count, bool transpose, const float* v) {
|
|
glUniformMatrix4fv(location, count, transpose ? GL_TRUE : GL_FALSE, v);
|
|
}
|
|
|
|
void OpenGLCommandList::UseProgram(unsigned int program) {
|
|
glUseProgram(program);
|
|
}
|
|
|
|
void OpenGLCommandList::BindFragDataLocation(unsigned int program, unsigned int colorNumber, const char* name) {
|
|
glBindFragDataLocation(program, colorNumber, name);
|
|
}
|
|
|
|
void OpenGLCommandList::BindFragDataLocationIndexed(unsigned int program, unsigned int colorNumber, unsigned int index, const char* name) {
|
|
glBindFragDataLocationIndexed(program, colorNumber, index, name);
|
|
}
|
|
|
|
void OpenGLCommandList::BeginQuery(unsigned int target, unsigned int id) {
|
|
glBeginQuery(target, id);
|
|
}
|
|
|
|
void OpenGLCommandList::EndQuery(unsigned int target) {
|
|
glEndQuery(target);
|
|
}
|
|
|
|
void OpenGLCommandList::GetQueryObjectiv(unsigned int id, unsigned int pname, int* params) {
|
|
glGetQueryObjectiv(id, pname, params);
|
|
}
|
|
|
|
void OpenGLCommandList::GetQueryObjectuiv(unsigned int id, unsigned int pname, unsigned int* params) {
|
|
glGetQueryObjectuiv(id, pname, params);
|
|
}
|
|
|
|
void OpenGLCommandList::ReadPixels(int x, int y, int width, int height, unsigned int format, unsigned int type, void* data) {
|
|
glReadPixels(x, y, width, height, format, type, data);
|
|
}
|
|
|
|
void OpenGLCommandList::BlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, unsigned int mask, unsigned int filter) {
|
|
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
|
}
|
|
|
|
void OpenGLCommandList::CopyImageSubData(unsigned int srcName, unsigned int srcTarget, int srcLevel, int srcX, int srcY, int srcZ, unsigned int dstName, unsigned int dstTarget, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) {
|
|
glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, width, height, depth);
|
|
}
|
|
|
|
void OpenGLCommandList::InvalidateFramebuffer(unsigned int target, unsigned int count, const unsigned int* attachments) {
|
|
glInvalidateFramebuffer(target, count, attachments);
|
|
}
|
|
|
|
void OpenGLCommandList::InvalidateSubFramebuffer(unsigned int target, unsigned int count, const unsigned int* attachments, int x, int y, int width, int height) {
|
|
glInvalidateSubFramebuffer(target, count, attachments, x, y, width, height);
|
|
}
|
|
|
|
void OpenGLCommandList::PushDebugGroup(unsigned int source, unsigned int id, int length, const char* message) {
|
|
glPushDebugGroup(source, id, length, message);
|
|
}
|
|
|
|
void OpenGLCommandList::PopDebugGroup() {
|
|
glPopDebugGroup();
|
|
}
|
|
|
|
void OpenGLCommandList::Shutdown() {
|
|
ReleaseComposedFramebuffer();
|
|
DisableConfiguredVertexAttributes();
|
|
if (m_internalVAO != 0) {
|
|
glDeleteVertexArrays(1, &m_internalVAO);
|
|
m_internalVAO = 0;
|
|
}
|
|
m_currentPipelineState = nullptr;
|
|
m_currentShader = nullptr;
|
|
}
|
|
|
|
void OpenGLCommandList::Reset() {
|
|
ReleaseComposedFramebuffer();
|
|
m_currentPipelineState = nullptr;
|
|
}
|
|
|
|
void OpenGLCommandList::Close() {
|
|
}
|
|
|
|
void OpenGLCommandList::ReleaseComposedFramebuffer() {
|
|
if (m_composedFramebuffer != nullptr) {
|
|
m_composedFramebuffer->Shutdown();
|
|
delete m_composedFramebuffer;
|
|
m_composedFramebuffer = nullptr;
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetShader(RHIShader* shader) {
|
|
m_currentShader = static_cast<OpenGLShader*>(shader);
|
|
if (m_currentShader) {
|
|
UseShader(m_currentShader->GetID());
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformInt(const char* name, int value) {
|
|
if (m_currentShader) {
|
|
glUniform1i(glGetUniformLocation(m_currentShader->GetID(), name), value);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformFloat(const char* name, float value) {
|
|
if (m_currentShader) {
|
|
glUniform1f(glGetUniformLocation(m_currentShader->GetID(), name), value);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformVec3(const char* name, float x, float y, float z) {
|
|
if (m_currentShader) {
|
|
glUniform3f(glGetUniformLocation(m_currentShader->GetID(), name), x, y, z);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformVec4(const char* name, float x, float y, float z, float w) {
|
|
if (m_currentShader) {
|
|
glUniform4f(glGetUniformLocation(m_currentShader->GetID(), name), x, y, z, w);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetUniformMat4(const char* name, const float* value) {
|
|
if (m_currentShader) {
|
|
glUniformMatrix4fv(glGetUniformLocation(m_currentShader->GetID(), name), 1, GL_FALSE, value);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
|
|
(void)resource;
|
|
(void)stateBefore;
|
|
(void)stateAfter;
|
|
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
|
}
|
|
|
|
void OpenGLCommandList::BeginRenderPass(RHIRenderPass* renderPass, RHIFramebuffer* framebuffer,
|
|
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) {
|
|
(void)renderArea;
|
|
(void)clearValueCount;
|
|
(void)clearValues;
|
|
|
|
if (!framebuffer) return;
|
|
|
|
OpenGLFramebuffer* glFramebuffer = static_cast<OpenGLFramebuffer*>(framebuffer);
|
|
glFramebuffer->Bind();
|
|
|
|
if (!renderPass) return;
|
|
|
|
OpenGLRenderPass* glRenderPass = static_cast<OpenGLRenderPass*>(renderPass);
|
|
if (glRenderPass) {
|
|
const AttachmentDesc* colorAttachments = glRenderPass->GetColorAttachments();
|
|
uint32_t colorCount = glRenderPass->GetColorAttachmentCount();
|
|
|
|
for (uint32_t i = 0; i < colorCount && i < clearValueCount; ++i) {
|
|
if (colorAttachments[i].loadOp == LoadAction::Clear) {
|
|
glClearBufferfv(GL_COLOR, i, &clearValues[i].color.r);
|
|
}
|
|
}
|
|
|
|
const AttachmentDesc* dsAttachment = glRenderPass->GetDepthStencilAttachment();
|
|
if (dsAttachment && clearValueCount > colorCount) {
|
|
if (dsAttachment->loadOp == LoadAction::Clear) {
|
|
glClearBufferfv(GL_DEPTH, 0, &clearValues[colorCount].depth);
|
|
}
|
|
if (dsAttachment->stencilLoadOp == LoadAction::Clear) {
|
|
float stencilValue = static_cast<float>(clearValues[colorCount].stencil);
|
|
glClearBufferfv(GL_STENCIL, 0, &stencilValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::EndRenderPass() {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void OpenGLCommandList::SetViewport(const Viewport& viewport) {
|
|
glViewport(static_cast<int>(viewport.topLeftX), static_cast<int>(viewport.topLeftY),
|
|
static_cast<int>(viewport.width), static_cast<int>(viewport.height));
|
|
}
|
|
|
|
void OpenGLCommandList::SetViewports(uint32_t count, const Viewport* viewports) {
|
|
std::vector<float> viewportsGL(count * 6);
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
viewportsGL[i * 6 + 0] = viewports[i].topLeftX;
|
|
viewportsGL[i * 6 + 1] = viewports[i].topLeftY;
|
|
viewportsGL[i * 6 + 2] = viewports[i].width;
|
|
viewportsGL[i * 6 + 3] = viewports[i].height;
|
|
viewportsGL[i * 6 + 4] = viewports[i].minDepth;
|
|
viewportsGL[i * 6 + 5] = viewports[i].maxDepth;
|
|
}
|
|
glViewportArrayv(0, count, viewportsGL.data());
|
|
}
|
|
|
|
void OpenGLCommandList::SetScissorRect(const Rect& rect) {
|
|
glScissor(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
|
|
}
|
|
|
|
void OpenGLCommandList::SetScissorRects(uint32_t count, const Rect* rects) {
|
|
std::vector<int> scissorGL(count * 4);
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
scissorGL[i * 4 + 0] = rects[i].left;
|
|
scissorGL[i * 4 + 1] = rects[i].top;
|
|
scissorGL[i * 4 + 2] = rects[i].right - rects[i].left;
|
|
scissorGL[i * 4 + 3] = rects[i].bottom - rects[i].top;
|
|
}
|
|
glScissorArrayv(0, count, scissorGL.data());
|
|
}
|
|
|
|
void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
|
|
if (count > 0 && renderTargets != nullptr) {
|
|
const bool requiresComposedFramebuffer = count > 1 || depthStencil != nullptr;
|
|
std::vector<GLenum> drawBuffers(count, GL_NONE);
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
if (renderTargets[i] != nullptr) {
|
|
drawBuffers[i] = ToOpenGLColorAttachment(i);
|
|
}
|
|
}
|
|
|
|
if (requiresComposedFramebuffer) {
|
|
uint32_t width = 0;
|
|
uint32_t height = 0;
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
auto* view = static_cast<OpenGLResourceView*>(renderTargets[i]);
|
|
const OpenGLTexture* texture = view != nullptr ? view->GetTextureResource() : nullptr;
|
|
if (texture != nullptr) {
|
|
width = texture->GetWidth();
|
|
height = texture->GetHeight();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((width == 0 || height == 0) && depthStencil != nullptr) {
|
|
auto* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
|
const OpenGLTexture* depthTexture = dsv != nullptr ? dsv->GetTextureResource() : nullptr;
|
|
if (depthTexture != nullptr) {
|
|
width = depthTexture->GetWidth();
|
|
height = depthTexture->GetHeight();
|
|
}
|
|
}
|
|
|
|
ReleaseComposedFramebuffer();
|
|
m_composedFramebuffer = new OpenGLFramebuffer();
|
|
if (!m_composedFramebuffer->Initialize(nullptr, width, height, count, renderTargets, depthStencil)) {
|
|
ReleaseComposedFramebuffer();
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
glDrawBuffers(0, nullptr);
|
|
return;
|
|
}
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_composedFramebuffer->GetFramebuffer());
|
|
} else {
|
|
ReleaseComposedFramebuffer();
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[0]);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view != nullptr ? view->GetFramebuffer() : 0);
|
|
}
|
|
|
|
glDrawBuffers(count, drawBuffers.data());
|
|
} else if (depthStencil) {
|
|
ReleaseComposedFramebuffer();
|
|
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
|
if (dsv && dsv->IsValid()) {
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
|
|
}
|
|
glDrawBuffers(0, nullptr);
|
|
} else {
|
|
ReleaseComposedFramebuffer();
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
(void)depthStencil;
|
|
}
|
|
|
|
void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
|
if (!renderTarget) return;
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTarget);
|
|
if (!view->IsValid()) return;
|
|
|
|
GLuint prevFBO = 0;
|
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
|
|
glClearColor(color[0], color[1], color[2], color[3]);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
|
|
}
|
|
|
|
void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
|
if (!depthStencil) return;
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencil);
|
|
if (!view->IsValid()) return;
|
|
|
|
GLuint prevFBO = 0;
|
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
|
|
glClearDepth(depth);
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
|
|
(void)stencil;
|
|
}
|
|
|
|
void OpenGLCommandList::SetPipelineState(RHIPipelineState* pipelineState) {
|
|
if (pipelineState) {
|
|
m_currentPipelineState = static_cast<OpenGLPipelineState*>(pipelineState);
|
|
pipelineState->Bind();
|
|
} else {
|
|
m_currentPipelineState = nullptr;
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetGraphicsDescriptorSets(
|
|
uint32_t firstSet,
|
|
uint32_t count,
|
|
RHIDescriptorSet** descriptorSets,
|
|
RHIPipelineLayout* pipelineLayout) {
|
|
OpenGLPipelineLayout* openGLPipelineLayout = static_cast<OpenGLPipelineLayout*>(pipelineLayout);
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
if (descriptorSets[i] != nullptr) {
|
|
static_cast<OpenGLDescriptorSet*>(descriptorSets[i])->BindWithPipelineLayout(
|
|
openGLPipelineLayout,
|
|
firstSet + i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetComputeDescriptorSets(
|
|
uint32_t firstSet,
|
|
uint32_t count,
|
|
RHIDescriptorSet** descriptorSets,
|
|
RHIPipelineLayout* pipelineLayout) {
|
|
OpenGLPipelineLayout* openGLPipelineLayout = static_cast<OpenGLPipelineLayout*>(pipelineLayout);
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
if (descriptorSets[i] != nullptr) {
|
|
static_cast<OpenGLDescriptorSet*>(descriptorSets[i])->BindWithPipelineLayout(
|
|
openGLPipelineLayout,
|
|
firstSet + i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) {
|
|
EnsureInternalVertexArrayBound();
|
|
DisableConfiguredVertexAttributes();
|
|
|
|
if (m_currentPipelineState != nullptr) {
|
|
const InputLayoutDesc& inputLayout = m_currentPipelineState->GetInputLayout();
|
|
if (!inputLayout.elements.empty()) {
|
|
for (uint32_t attributeIndex = 0; attributeIndex < inputLayout.elements.size(); ++attributeIndex) {
|
|
const InputElementDesc& element = inputLayout.elements[attributeIndex];
|
|
if (element.inputSlot < startSlot || element.inputSlot >= startSlot + count) {
|
|
continue;
|
|
}
|
|
|
|
const uint32_t bindingIndex = element.inputSlot - startSlot;
|
|
if (buffers[bindingIndex] == nullptr) {
|
|
continue;
|
|
}
|
|
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffers[bindingIndex]);
|
|
if (!view->IsValid()) {
|
|
continue;
|
|
}
|
|
|
|
OpenGLVertexAttribFormat attributeFormat = {};
|
|
if (!GetOpenGLVertexAttribFormat(static_cast<Format>(element.format), attributeFormat)) {
|
|
continue;
|
|
}
|
|
|
|
const GLuint glBuffer = view->GetBuffer();
|
|
const uint32_t stride = strides[bindingIndex] > 0 ? strides[bindingIndex] : view->GetBufferStride();
|
|
const uint64_t offset = view->GetBufferOffset() + offsets[bindingIndex] + element.alignedByteOffset;
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
|
|
glEnableVertexAttribArray(attributeIndex);
|
|
if (attributeFormat.integer) {
|
|
glVertexAttribIPointer(
|
|
attributeIndex,
|
|
attributeFormat.componentCount,
|
|
attributeFormat.type,
|
|
static_cast<GLsizei>(stride),
|
|
reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
|
|
} else {
|
|
glVertexAttribPointer(
|
|
attributeIndex,
|
|
attributeFormat.componentCount,
|
|
attributeFormat.type,
|
|
attributeFormat.normalized,
|
|
static_cast<GLsizei>(stride),
|
|
reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
|
|
}
|
|
m_enabledVertexAttributes.push_back(attributeIndex);
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
if (!buffers[i]) continue;
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffers[i]);
|
|
if (!view->IsValid()) continue;
|
|
|
|
GLuint glBuffer = view->GetBuffer();
|
|
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
|
|
glEnableVertexAttribArray(startSlot + i);
|
|
const uint32_t stride = strides[i] > 0 ? strides[i] : view->GetBufferStride();
|
|
const uint64_t offset = view->GetBufferOffset() + offsets[i];
|
|
glVertexAttribPointer(startSlot + i, stride / sizeof(float), GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
|
|
m_enabledVertexAttributes.push_back(startSlot + i);
|
|
}
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void OpenGLCommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
|
|
if (!buffer) return;
|
|
EnsureInternalVertexArrayBound();
|
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffer);
|
|
if (!view->IsValid()) return;
|
|
|
|
GLuint glBuffer = view->GetBuffer();
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glBuffer);
|
|
(void)offset;
|
|
}
|
|
|
|
void OpenGLCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {
|
|
if (!dst || !src) return;
|
|
OpenGLResourceView* dstView = static_cast<OpenGLResourceView*>(dst);
|
|
OpenGLResourceView* srcView = static_cast<OpenGLResourceView*>(src);
|
|
if (!dstView->IsValid() || !srcView->IsValid()) return;
|
|
|
|
GLuint dstTex = dstView->GetTexture();
|
|
GLuint srcTex = srcView->GetTexture();
|
|
const OpenGLTexture* dstTexture = dstView->GetTextureResource();
|
|
const OpenGLTexture* srcTexture = srcView->GetTextureResource();
|
|
if (dstTex && srcTex && dstTexture != nullptr && srcTexture != nullptr) {
|
|
const GLuint srcTarget = ToOpenGL(srcTexture->GetOpenGLType());
|
|
const GLuint dstTarget = ToOpenGL(dstTexture->GetOpenGLType());
|
|
const GLsizei copyWidth = static_cast<GLsizei>(std::min(srcTexture->GetWidth(), dstTexture->GetWidth()));
|
|
const GLsizei copyHeight = static_cast<GLsizei>(std::min(srcTexture->GetHeight(), dstTexture->GetHeight()));
|
|
const GLsizei copyDepth = static_cast<GLsizei>(std::max<uint32_t>(1u, std::min(srcTexture->GetDepth(), dstTexture->GetDepth())));
|
|
glCopyImageSubData(srcTex, srcTarget, 0, 0, 0, 0,
|
|
dstTex, dstTarget, 0, 0, 0, 0,
|
|
copyWidth, copyHeight, copyDepth);
|
|
}
|
|
}
|
|
|
|
void OpenGLCommandList::Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) {
|
|
glDrawArraysInstanced(GL_TRIANGLES, static_cast<GLint>(startVertex), static_cast<GLsizei>(vertexCount), static_cast<GLsizei>(instanceCount));
|
|
}
|
|
|
|
void OpenGLCommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) {
|
|
glDrawElementsInstanced(GL_TRIANGLES, static_cast<GLsizei>(indexCount), GL_UNSIGNED_INT,
|
|
reinterpret_cast<const void*>(startIndex * sizeof(GLuint)), static_cast<GLsizei>(instanceCount));
|
|
}
|
|
|
|
void OpenGLCommandList::SetPrimitiveTopology(PrimitiveTopology topology) {
|
|
m_primitiveType = ToOpenGL(topology);
|
|
}
|
|
|
|
void OpenGLCommandList::SetStencilRef(uint8_t ref) {
|
|
glStencilFunc(GL_FRONT_AND_BACK, ref, 0xFF);
|
|
}
|
|
|
|
void OpenGLCommandList::SetBlendFactor(const float factor[4]) {
|
|
glBlendColor(factor[0], factor[1], factor[2], factor[3]);
|
|
}
|
|
|
|
void OpenGLCommandList::EnsureInternalVertexArrayBound() {
|
|
if (m_internalVAO == 0) {
|
|
glGenVertexArrays(1, &m_internalVAO);
|
|
}
|
|
|
|
m_currentVAO = m_internalVAO;
|
|
glBindVertexArray(m_internalVAO);
|
|
}
|
|
|
|
void OpenGLCommandList::DisableConfiguredVertexAttributes() {
|
|
for (unsigned int attributeIndex : m_enabledVertexAttributes) {
|
|
glDisableVertexAttribArray(attributeIndex);
|
|
}
|
|
m_enabledVertexAttributes.clear();
|
|
}
|
|
|
|
} // namespace RHI
|
|
} // namespace XCEngine
|