mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (MG_Backend/DirectVulkan): refactor VkRenderPassManager and hook it up (this commit only compiles and does not work)
This commit is contained in:
@@ -58,7 +58,7 @@ namespace MobileGL::MG_ConfigLoader {
|
|||||||
|
|
||||||
inline void InitBackendType() {
|
inline void InitBackendType() {
|
||||||
String backendTypeStr;
|
String backendTypeStr;
|
||||||
QueryEnvVariable("MOBILEGL_BACKEND_TYPE", backendTypeStr, "DirectGLES");
|
QueryEnvVariable("MOBILEGL_BACKEND_TYPE", backendTypeStr, "DirectVulkan");
|
||||||
#define ENTRY(backendType) \
|
#define ENTRY(backendType) \
|
||||||
if (backendTypeStr == #backendType) { \
|
if (backendTypeStr == #backendType) { \
|
||||||
MG_Config::ActiveBackendType = BackendType::backendType; \
|
MG_Config::ActiveBackendType = BackendType::backendType; \
|
||||||
|
|||||||
@@ -17,165 +17,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {}
|
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {}
|
||||||
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {}
|
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {}
|
||||||
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {}
|
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {}
|
||||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {
|
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {}
|
||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsBaseVertex called with null VulkanRenderer");
|
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsBaseVertex called with null GL context");
|
|
||||||
|
|
||||||
if (count < 0) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: count (%d) must be non-negative", count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mode != GL_TRIANGLES) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: primitive mode %u is not supported yet", mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeT indexSize = 0;
|
|
||||||
switch (type) {
|
|
||||||
case GL_UNSIGNED_SHORT:
|
|
||||||
indexSize = sizeof(Uint16);
|
|
||||||
break;
|
|
||||||
case GL_UNSIGNED_INT:
|
|
||||||
indexSize = sizeof(Uint32);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: index type %u is not supported yet", type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
if (!vao) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: no bound VAO");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
|
||||||
if (!indexBuffer) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: no bound ELEMENT_ARRAY_BUFFER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexData = indexBuffer->GetDataReadOnly();
|
|
||||||
if (!indexData || indexData->empty()) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: ELEMENT_ARRAY_BUFFER has no data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SizeT byteOffset = reinterpret_cast<SizeT>(indices);
|
|
||||||
const SizeT requiredBytes = static_cast<SizeT>(count) * indexSize;
|
|
||||||
if (byteOffset + requiredBytes > indexBuffer->GetSize()) {
|
|
||||||
MGLOG_W("DrawElementsBaseVertex skipped: index range out of bounds (offset=%zu, size=%zu, buffer=%zu)",
|
|
||||||
byteOffset, requiredBytes, indexBuffer->GetSize());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawElementPayload payload{};
|
|
||||||
payload.drawArray.mode = mode;
|
|
||||||
payload.drawArray.first = 0;
|
|
||||||
payload.drawArray.count = count;
|
|
||||||
const auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
payload.drawArray.program = currentProgram ? currentProgram.get() : nullptr;
|
|
||||||
payload.drawArray.vertexArray = vao.get();
|
|
||||||
payload.indexType = type;
|
|
||||||
payload.indexByteOffset = byteOffset;
|
|
||||||
payload.baseVertex = basevertex;
|
|
||||||
|
|
||||||
pVulkanRenderer->DrawElements(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
|
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
|
||||||
GLsizei drawcount, const GLint* basevertex) {
|
GLsizei drawcount, const GLint* basevertex) {}
|
||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsBaseVertex called with null VulkanRenderer");
|
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElementsBaseVertex called with null GL context");
|
|
||||||
|
|
||||||
if (drawcount < 0) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: drawcount (%d) must be non-negative", drawcount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (drawcount == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!count || !indices || !basevertex) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: count/indices/basevertex pointer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mode != GL_TRIANGLES) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: primitive mode %u is not supported yet", mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeT indexSize = 0;
|
|
||||||
switch (type) {
|
|
||||||
case GL_UNSIGNED_SHORT:
|
|
||||||
indexSize = sizeof(Uint16);
|
|
||||||
break;
|
|
||||||
case GL_UNSIGNED_INT:
|
|
||||||
indexSize = sizeof(Uint32);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: index type %u is not supported yet", type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
if (!vao) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: no bound VAO");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
|
||||||
if (!indexBuffer) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: no bound ELEMENT_ARRAY_BUFFER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexData = indexBuffer->GetDataReadOnly();
|
|
||||||
if (!indexData || indexData->empty()) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: ELEMENT_ARRAY_BUFFER has no data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
Vector<DrawElementPayload> payloads;
|
|
||||||
payloads.reserve(static_cast<SizeT>(drawcount));
|
|
||||||
for (GLsizei i = 0; i < drawcount; ++i) {
|
|
||||||
if (count[i] < 0) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: count[%d] (%d) must be non-negative", i, count[i]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (count[i] == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SizeT byteOffset = reinterpret_cast<SizeT>(indices[i]);
|
|
||||||
const SizeT requiredBytes = static_cast<SizeT>(count[i]) * indexSize;
|
|
||||||
if (byteOffset + requiredBytes > indexBuffer->GetSize()) {
|
|
||||||
MGLOG_W("MultiDrawElementsBaseVertex skipped: draw[%d] index range out of bounds (offset=%zu, "
|
|
||||||
"size=%zu, buffer=%zu)",
|
|
||||||
i, byteOffset, requiredBytes, indexBuffer->GetSize());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawElementPayload payload{};
|
|
||||||
payload.drawArray.mode = mode;
|
|
||||||
payload.drawArray.first = 0;
|
|
||||||
payload.drawArray.count = count[i];
|
|
||||||
payload.drawArray.program = currentProgram ? currentProgram.get() : nullptr;
|
|
||||||
payload.drawArray.vertexArray = vao.get();
|
|
||||||
payload.indexType = type;
|
|
||||||
payload.indexByteOffset = byteOffset;
|
|
||||||
payload.baseVertex = basevertex[i];
|
|
||||||
payloads.push_back(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payloads.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pVulkanRenderer->MultiDrawElements(payloads);
|
|
||||||
}
|
|
||||||
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {}
|
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {}
|
||||||
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {}
|
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {}
|
||||||
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
|
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
|
||||||
@@ -206,181 +52,44 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
|
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElements called with null GL context");
|
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElements called with null GL context");
|
||||||
|
|
||||||
if (drawcount < 0) {
|
Vector<DrawElementCmd> cmds;
|
||||||
MGLOG_W("MultiDrawElements skipped: drawcount (%d) must be non-negative", drawcount);
|
cmds.reserve(static_cast<SizeT>(drawcount));
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (drawcount == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!count || !indices) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: count/indices pointer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mode != GL_TRIANGLES) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: primitive mode %u is not supported yet", mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeT indexSize = 0;
|
|
||||||
switch (type) {
|
|
||||||
case GL_UNSIGNED_SHORT:
|
|
||||||
indexSize = sizeof(Uint16);
|
|
||||||
break;
|
|
||||||
case GL_UNSIGNED_INT:
|
|
||||||
indexSize = sizeof(Uint32);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MGLOG_W("MultiDrawElements skipped: index type %u is not supported yet", type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
if (!vao) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: no bound VAO");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
|
||||||
if (!indexBuffer) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: no bound ELEMENT_ARRAY_BUFFER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexData = indexBuffer->GetDataReadOnly();
|
|
||||||
if (!indexData || indexData->empty()) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: ELEMENT_ARRAY_BUFFER has no data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
Vector<DrawElementPayload> payloads;
|
|
||||||
payloads.reserve(static_cast<SizeT>(drawcount));
|
|
||||||
for (GLsizei i = 0; i < drawcount; ++i) {
|
for (GLsizei i = 0; i < drawcount; ++i) {
|
||||||
if (count[i] < 0) {
|
|
||||||
MGLOG_W("MultiDrawElements skipped: count[%d] (%d) must be non-negative", i, count[i]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (count[i] == 0) {
|
if (count[i] == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto byteOffset = reinterpret_cast<SizeT>(indices[i]);
|
DrawElementCmd payload{};
|
||||||
const SizeT requiredBytes = static_cast<SizeT>(count[i]) * indexSize;
|
payload.mode = mode;
|
||||||
if (byteOffset + requiredBytes > indexBuffer->GetSize()) {
|
payload.first = 0;
|
||||||
MGLOG_W("MultiDrawElements skipped: draw[%d] index range out of bounds (offset=%zu, size=%zu, "
|
payload.count = count[i];
|
||||||
"buffer=%zu)",
|
|
||||||
i, byteOffset, requiredBytes, indexBuffer->GetSize());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawElementPayload payload{};
|
|
||||||
payload.drawArray.mode = mode;
|
|
||||||
payload.drawArray.first = 0;
|
|
||||||
payload.drawArray.count = count[i];
|
|
||||||
payload.drawArray.program = currentProgram ? currentProgram.get() : nullptr;
|
|
||||||
payload.drawArray.vertexArray = vao.get();
|
|
||||||
payload.indexType = type;
|
payload.indexType = type;
|
||||||
payload.indexByteOffset = byteOffset;
|
payload.indexByteOffset = reinterpret_cast<SizeT>(indices[i]);
|
||||||
payloads.push_back(payload);
|
cmds.push_back(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payloads.empty()) {
|
if (cmds.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pVulkanRenderer->MultiDrawElements(payloads);
|
pVulkanRenderer->MultiDrawElements(cmds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear(GLbitfield mask) {
|
void Clear(GLbitfield mask) {
|
||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer");
|
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer");
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::Clear called with null GL context");
|
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::Clear called with null GL context");
|
||||||
|
pVulkanRenderer->Clear(mask);
|
||||||
const auto& drawFboSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw);
|
|
||||||
const auto drawFbo = drawFboSlot.GetBoundObject();
|
|
||||||
const auto defaultFboInfo = MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo;
|
|
||||||
const auto defaultFbo = defaultFboInfo ? defaultFboInfo->defaultFBO : nullptr;
|
|
||||||
const Bool isDefaultFboTarget = (drawFbo == defaultFbo) || (drawFbo == nullptr && defaultFbo != nullptr);
|
|
||||||
Uint drawFboExternalIndex = 0;
|
|
||||||
if (drawFbo) {
|
|
||||||
drawFboExternalIndex = drawFbo->GetExternalIndex();
|
|
||||||
} else if (defaultFbo) {
|
|
||||||
drawFboExternalIndex = defaultFbo->GetExternalIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& clearColor = MG_State::pGLContext->GetClearColor();
|
|
||||||
const auto clearDepth = MG_State::pGLContext->GetClearDepth();
|
|
||||||
const auto clearStencil = static_cast<Uint32>(MG_State::pGLContext->GetClearStencil());
|
|
||||||
pVulkanRenderer->QueueClearRequest(mask, clearColor, clearDepth, clearStencil,
|
|
||||||
drawFboExternalIndex,
|
|
||||||
isDefaultFboTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
|
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElements called with null GL context");
|
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElements called with null GL context");
|
||||||
|
|
||||||
if (count < 0) {
|
DrawElementCmd payload{};
|
||||||
MGLOG_W("DrawElements skipped: count (%d) must be non-negative", count);
|
payload.mode = mode;
|
||||||
return;
|
payload.first = 0;
|
||||||
}
|
payload.count = count;
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode != GL_TRIANGLES) {
|
|
||||||
MGLOG_W("DrawElements skipped: primitive mode %u is not supported yet", mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeT indexSize = 0;
|
|
||||||
switch (type) {
|
|
||||||
case GL_UNSIGNED_SHORT:
|
|
||||||
indexSize = sizeof(Uint16);
|
|
||||||
break;
|
|
||||||
case GL_UNSIGNED_INT:
|
|
||||||
indexSize = sizeof(Uint32);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MGLOG_W("DrawElements skipped: index type %u is not supported yet", type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
if (!vao) {
|
|
||||||
MGLOG_W("DrawElements skipped: no bound VAO");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
|
||||||
if (!indexBuffer) {
|
|
||||||
MGLOG_W("DrawElements skipped: no bound ELEMENT_ARRAY_BUFFER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto indexData = indexBuffer->GetDataReadOnly();
|
|
||||||
if (!indexData || indexData->empty()) {
|
|
||||||
MGLOG_W("DrawElements skipped: ELEMENT_ARRAY_BUFFER has no data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto byteOffset = reinterpret_cast<SizeT>(indices);
|
|
||||||
const SizeT requiredBytes = static_cast<SizeT>(count) * indexSize;
|
|
||||||
if (byteOffset + requiredBytes > indexBuffer->GetSize()) {
|
|
||||||
MGLOG_W("DrawElements skipped: index range out of bounds (offset=%zu, size=%zu, buffer=%zu)", byteOffset,
|
|
||||||
requiredBytes, indexBuffer->GetSize());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawElementPayload payload{};
|
|
||||||
payload.drawArray.mode = mode;
|
|
||||||
payload.drawArray.first = 0;
|
|
||||||
payload.drawArray.count = count;
|
|
||||||
const auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
payload.drawArray.program = currentProgram ? currentProgram.get() : nullptr;
|
|
||||||
payload.drawArray.vertexArray = vao.get();
|
|
||||||
payload.indexType = type;
|
payload.indexType = type;
|
||||||
payload.indexByteOffset = byteOffset;
|
payload.indexByteOffset = reinterpret_cast<SizeT>(indices);
|
||||||
|
|
||||||
pVulkanRenderer->DrawElements(payload);
|
pVulkanRenderer->DrawElements(payload);
|
||||||
}
|
}
|
||||||
@@ -389,34 +98,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArrays called with null VulkanRenderer");
|
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArrays called with null VulkanRenderer");
|
||||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArrays called with null GL context");
|
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArrays called with null GL context");
|
||||||
|
|
||||||
if (first < 0) {
|
DrawArrayCmd payload{};
|
||||||
MGLOG_W("DrawArrays skipped: first (%d) must be non-negative", first);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0) {
|
|
||||||
MGLOG_W("DrawArrays skipped: count (%d) must be non-negative", count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode != GL_TRIANGLES) {
|
|
||||||
MGLOG_W("DrawArrays skipped: primitive mode %u is not supported yet", mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawArrayPayload payload{};
|
|
||||||
payload.mode = mode;
|
payload.mode = mode;
|
||||||
payload.first = first;
|
payload.first = first;
|
||||||
payload.count = count;
|
payload.count = count;
|
||||||
const auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
payload.program = currentProgram ? currentProgram.get() : nullptr;
|
|
||||||
|
|
||||||
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
payload.vertexArray = vao ? vao.get() : nullptr;
|
|
||||||
|
|
||||||
pVulkanRenderer->DrawArrays(payload);
|
pVulkanRenderer->DrawArrays(payload);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,11 +475,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (!samplerToUse) {
|
if (!samplerToUse) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
VkTextureManager::TextureResource resource;
|
||||||
if (!m_textureManager->SyncTextureAndGetDescriptor(*texture, outImageInfo)) {
|
if (!m_textureManager->SyncTextureAndGetDescriptor(*texture, resource)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
outImageInfo.sampler = m_samplerManager->GetOrCreateSampler(*samplerToUse);
|
outImageInfo = {
|
||||||
|
.sampler = m_samplerManager->GetOrCreateSampler(*samplerToUse),
|
||||||
|
.imageView = resource.view,
|
||||||
|
.imageLayout = resource.layout,
|
||||||
|
};
|
||||||
return outImageInfo.sampler != VK_NULL_HANDLE;
|
return outImageInfo.sampler != VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,27 +682,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool UniformDescriptorBinder::BindProgramUniformBuffers(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout,
|
Bool UniformDescriptorBinder::BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||||
const MG_State::GLState::ProgramObject& program,
|
const MG_State::GLState::ProgramObject& program,
|
||||||
Uint32 frameIndex) {
|
Uint32 frameIndex) {
|
||||||
if (m_frames.empty()) {
|
|
||||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: binder is not initialized");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (frameIndex >= m_frames.size()) {
|
|
||||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: invalid frame index %u", frameIndex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgramLayout* layout = GetOrCreateProgramLayout(program);
|
ProgramLayout* layout = GetOrCreateProgramLayout(program);
|
||||||
if (!layout || layout->pipelineLayout == VK_NULL_HANDLE || layout->descriptorSetLayout == VK_NULL_HANDLE) {
|
|
||||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: cannot get program layout");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (layout->pipelineLayout != pipelineLayout) {
|
|
||||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: pipelineLayout mismatch");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& frame = m_frames[frameIndex];
|
auto& frame = m_frames[frameIndex];
|
||||||
if (frame.descriptorPools.empty()) {
|
if (frame.descriptorPools.empty()) {
|
||||||
@@ -837,7 +824,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
vkUpdateDescriptorSets(m_device, static_cast<Uint32>(writes.size()), writes.data(), 0, nullptr);
|
vkUpdateDescriptorSets(m_device, static_cast<Uint32>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet,
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, layout->pipelineLayout, 0, 1, &descriptorSet,
|
||||||
static_cast<Uint32>(dynamicOffsets.size()), dynamicOffsets.data());
|
static_cast<Uint32>(dynamicOffsets.size()), dynamicOffsets.data());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void BeginFrame(Uint32 frameIndex);
|
void BeginFrame(Uint32 frameIndex);
|
||||||
VkPipelineLayout GetOrCreatePipelineLayout(const MG_State::GLState::ProgramObject& program);
|
VkPipelineLayout GetOrCreatePipelineLayout(const MG_State::GLState::ProgramObject& program);
|
||||||
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout,
|
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||||
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex);
|
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SizeT VkClearManager::CollectGarbage() {
|
SizeT VkClearManager::CollectGarbage() {
|
||||||
|
m_gcCounter++;
|
||||||
|
if (m_gcCounter != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SizeT count = 0;
|
SizeT count = 0;
|
||||||
for (const auto& [raw, weak]: m_aliveObjects) {
|
for (const auto& [raw, weak]: m_aliveObjects) {
|
||||||
if (weak.expired()) {
|
if (weak.expired()) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void PopPendingClear(MG_State::GLState::ITextureObject* texture);
|
void PopPendingClear(MG_State::GLState::ITextureObject* texture);
|
||||||
SizeT CollectGarbage();
|
SizeT CollectGarbage();
|
||||||
private:
|
private:
|
||||||
|
Uint8 m_gcCounter = 0;
|
||||||
UnorderedMap<MG_State::GLState::ITextureObject*, ClearAttachmentPayload> m_pendingClears;
|
UnorderedMap<MG_State::GLState::ITextureObject*, ClearAttachmentPayload> m_pendingClears;
|
||||||
UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> m_aliveObjects;
|
UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> m_aliveObjects;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
Int width = 0;
|
Int width = 0;
|
||||||
Int height = 0;
|
Int height = 0;
|
||||||
Vector<VkAttachmentDescription> colorAttachmentDescriptions(validDrawBufCount);
|
Vector<VkAttachmentDescription> attachmentDescriptions(validDrawBufCount);
|
||||||
Vector<VkAttachmentReference> colorAttachmentRefs(validDrawBufCount);
|
Vector<VkAttachmentReference> colorAttachmentRefs(validDrawBufCount);
|
||||||
Vector<VkDescriptorImageInfo> descriptorImageInfo(validDrawBufCount);
|
Vector<VkTextureManager::TextureResource> textureResources(validDrawBufCount);
|
||||||
// This should automatically work on default & offscreen FBO
|
// This should automatically work on default & offscreen FBO
|
||||||
// assuming default FBO has the right param
|
// assuming default FBO has the right param
|
||||||
for (Int i = 0; i < validDrawBufCount; ++i) {
|
for (Int i = 0; i < validDrawBufCount; ++i) {
|
||||||
@@ -110,7 +110,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
const auto textureTarget = texture->GetTarget();
|
const auto textureTarget = texture->GetTarget();
|
||||||
|
|
||||||
// Color attachment description
|
// Color attachment description
|
||||||
VkAttachmentDescription& desc = colorAttachmentDescriptions[i];
|
VkAttachmentDescription& desc = attachmentDescriptions[i];
|
||||||
switch (textureTarget) {
|
switch (textureTarget) {
|
||||||
case TextureTarget::Texture2D: {
|
case TextureTarget::Texture2D: {
|
||||||
auto* texture2d =
|
auto* texture2d =
|
||||||
@@ -135,8 +135,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (height == 0)
|
if (height == 0)
|
||||||
height = texture2d->GetBaseSize().y();
|
height = texture2d->GetBaseSize().y();
|
||||||
|
|
||||||
Bool ok = m_textureManager.SyncTextureAndGetDescriptor(*texture, descriptorImageInfo[i]);
|
Bool ok = m_textureManager.SyncTextureAndGetDescriptor(*texture, textureResources[i]);
|
||||||
MOBILEGL_ASSERT(ok, "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed");
|
MOBILEGL_ASSERT(ok, "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -153,9 +153,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Depth attachment description
|
// Depth attachment description
|
||||||
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
|
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
|
||||||
VkAttachmentDescription depthAttachmentDescription;
|
VkAttachmentDescription depthAttachmentDescription;
|
||||||
if (depthAtt.IsComplete()) {
|
VkTextureManager::TextureResource depthTextureResource;
|
||||||
|
if (depthAtt.IsComplete() && depthAtt.IsTexture()) {
|
||||||
|
auto& texture = *depthAtt.GetTexture();
|
||||||
depthAttachmentDescription.format =
|
depthAttachmentDescription.format =
|
||||||
MG_Util::ConvertTextureInternalFormatToVkEnum(depthAtt.GetTexture()->GetFormat());
|
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
|
||||||
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
depthAttachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
depthAttachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
depthAttachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
depthAttachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
@@ -165,6 +167,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
depthAttachmentDescription.finalLayout = isDefaultFbo ?
|
depthAttachmentDescription.finalLayout = isDefaultFbo ?
|
||||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR :
|
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR :
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
Bool ok = m_textureManager.SyncTextureAndGetDescriptor(texture, depthTextureResource);
|
||||||
|
MOBILEGL_ASSERT(ok, "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at depth attachment");
|
||||||
|
attachmentDescriptions.emplace_back(depthAttachmentDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth attachment ref
|
// Depth attachment ref
|
||||||
@@ -190,8 +195,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
renderPassCreateInfo.pNext = VK_NULL_HANDLE;
|
renderPassCreateInfo.pNext = VK_NULL_HANDLE;
|
||||||
renderPassCreateInfo.flags = 0;
|
renderPassCreateInfo.flags = 0;
|
||||||
renderPassCreateInfo.attachmentCount = colorAttachmentDescriptions.size();
|
renderPassCreateInfo.attachmentCount = attachmentDescriptions.size();
|
||||||
renderPassCreateInfo.pAttachments = colorAttachmentDescriptions.data();
|
renderPassCreateInfo.pAttachments = attachmentDescriptions.data();
|
||||||
renderPassCreateInfo.subpassCount = 1;
|
renderPassCreateInfo.subpassCount = 1;
|
||||||
renderPassCreateInfo.pSubpasses = &subpassDesc;
|
renderPassCreateInfo.pSubpasses = &subpassDesc;
|
||||||
renderPassCreateInfo.dependencyCount = 0;
|
renderPassCreateInfo.dependencyCount = 0;
|
||||||
@@ -200,9 +205,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VK_VERIFY(vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &renderPass));
|
VK_VERIFY(vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &renderPass));
|
||||||
|
|
||||||
Vector<VkImageView> attachmentViews(descriptorImageInfo.size(), VK_NULL_HANDLE);
|
Vector<VkImageView> attachmentViews(textureResources.size(), VK_NULL_HANDLE);
|
||||||
for (Int i = 0; i < descriptorImageInfo.size(); i++) {
|
for (Int i = 0; i < textureResources.size(); i++) {
|
||||||
attachmentViews[i] = descriptorImageInfo[i].imageView;
|
attachmentViews[i] = textureResources[i].view;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Framebuffer
|
// Framebuffer
|
||||||
@@ -219,23 +224,22 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer));
|
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer));
|
||||||
IntVec2 extent = {width, height};
|
IntVec2 extent = {width, height};
|
||||||
m_renderPasses[hash] = { renderPass, framebuffer, Move(descriptorImageInfo), extent };
|
m_renderPasses[hash] = { renderPass, framebuffer, Move(textureResources), extent, 1 };
|
||||||
return m_renderPasses[hash];
|
return m_renderPasses[hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool VkRenderPassManager::StartRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry) {
|
Bool VkRenderPassManager::BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry) {
|
||||||
if (m_activeRenderPass != nullptr)
|
// TODO: Transition all the attachments into proper layout before starting the render pass
|
||||||
return false;
|
|
||||||
|
|
||||||
m_activeRenderPass = &renderPassEntry;
|
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo;
|
VkRenderPassBeginInfo renderPassBeginInfo;
|
||||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
renderPassBeginInfo.pNext = nullptr;
|
renderPassBeginInfo.pNext = nullptr;
|
||||||
renderPassBeginInfo.renderPass = m_activeRenderPass->renderPass;
|
renderPassBeginInfo.renderPass = renderPassEntry.renderPass;
|
||||||
renderPassBeginInfo.framebuffer = m_activeRenderPass->framebuffer;
|
renderPassBeginInfo.framebuffer = renderPassEntry.framebuffer;
|
||||||
renderPassBeginInfo.renderArea.offset = { 0, 0 };
|
renderPassBeginInfo.renderArea.offset = { 0, 0 };
|
||||||
renderPassBeginInfo.renderArea.extent = {
|
renderPassBeginInfo.renderArea.extent = {
|
||||||
(Uint32)m_activeRenderPass->extent.x(), (Uint32)m_activeRenderPass->extent.y() };
|
(Uint32)renderPassEntry.extent.x(), (Uint32)renderPassEntry.extent.y() };
|
||||||
|
|
||||||
// TODO: should query proper clear color
|
// TODO: should query proper clear color
|
||||||
VkClearValue clearValue;
|
VkClearValue clearValue;
|
||||||
@@ -251,8 +255,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bool VkRenderPassManager::EndRenderPass(VkCommandBuffer commandBuffer) {
|
Bool VkRenderPassManager::EndRenderPass(VkCommandBuffer commandBuffer) {
|
||||||
if (m_activeRenderPass == nullptr)
|
|
||||||
return false;
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
static inline VkDevice s_device;
|
static inline VkDevice s_device;
|
||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
Vector<VkDescriptorImageInfo> descriptorImageInfo;
|
Vector<VkTextureManager::TextureResource> textureResources;
|
||||||
IntVec2 extent = {0, 0};
|
IntVec2 extent = {0, 0};
|
||||||
|
Uint32 subpass = 0;
|
||||||
|
|
||||||
~RenderPassEntry() {
|
~RenderPassEntry() {
|
||||||
if (renderPass != VK_NULL_HANDLE) {
|
if (renderPass != VK_NULL_HANDLE) {
|
||||||
@@ -46,16 +47,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
HashType ComputeHash(const MG_State::GLState::FramebufferObject& fbo) const;
|
HashType ComputeHash(const MG_State::GLState::FramebufferObject& fbo) const;
|
||||||
RenderPassEntry& GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo);
|
RenderPassEntry& GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo);
|
||||||
RenderPassEntry* GetActiveRenderPass() const { return m_activeRenderPass; }
|
static Bool BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry);
|
||||||
Bool StartRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry);
|
static Bool EndRenderPass(VkCommandBuffer commandBuffer);
|
||||||
Bool EndRenderPass(VkCommandBuffer commandBuffer);
|
|
||||||
private:
|
private:
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
const VulkanRendererConfig& m_config;
|
const VulkanRendererConfig& m_config;
|
||||||
VkClearManager& m_clearManager;
|
VkClearManager& m_clearManager;
|
||||||
VkTextureManager& m_textureManager;
|
VkTextureManager& m_textureManager;
|
||||||
UnorderedMap<Uint64, RenderPassEntry> m_renderPasses;
|
UnorderedMap<Uint64, RenderPassEntry> m_renderPasses;
|
||||||
RenderPassEntry* m_activeRenderPass = nullptr;
|
|
||||||
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
||||||
};
|
};
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bool VkTextureManager::SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture,
|
Bool VkTextureManager::SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture,
|
||||||
VkDescriptorImageInfo& outImageInfo) {
|
TextureResource& outTextureResource) {
|
||||||
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE");
|
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE");
|
||||||
|
|
||||||
auto it = m_textureResources.find(texture.GetExternalIndex());
|
auto it = m_textureResources.find(texture.GetExternalIndex());
|
||||||
@@ -56,15 +56,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->second.view == VK_NULL_HANDLE) {
|
outTextureResource = it->second;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
outImageInfo.sampler = VK_NULL_HANDLE;
|
|
||||||
outImageInfo.imageView = it->second.view;
|
|
||||||
// Will be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
||||||
// Shouldn't hardcode VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL here
|
|
||||||
// outImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
||||||
|
|||||||
@@ -28,17 +28,6 @@ public:
|
|||||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
Bool Initialize(const InitInfo& initInfo);
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
Bool SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture, VkDescriptorImageInfo& outImageInfo);
|
|
||||||
|
|
||||||
|
|
||||||
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
|
||||||
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
|
||||||
VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask,
|
|
||||||
VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask);
|
|
||||||
private:
|
|
||||||
struct TextureResource {
|
struct TextureResource {
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
VmaAllocation allocation = nullptr;
|
VmaAllocation allocation = nullptr;
|
||||||
@@ -50,6 +39,19 @@ private:
|
|||||||
Uint textureExternalIndex = 0;
|
Uint textureExternalIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Bool Initialize(const InitInfo& initInfo);
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
Bool SyncTextureAndGetDescriptor(
|
||||||
|
MG_State::GLState::ITextureObject& texture, TextureResource& outTextureResource);
|
||||||
|
|
||||||
|
|
||||||
|
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
||||||
|
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
||||||
|
VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask,
|
||||||
|
VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask);
|
||||||
|
private:
|
||||||
|
|
||||||
Bool SyncTexture(MG_State::GLState::ITextureObject &texture,
|
Bool SyncTexture(MG_State::GLState::ITextureObject &texture,
|
||||||
TextureResource &outResource);
|
TextureResource &outResource);
|
||||||
Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -32,16 +32,23 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
} // namespace MobileGL::MG_State::GLState
|
} // namespace MobileGL::MG_State::GLState
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
struct DrawArrayPayload {
|
enum class DrawSetupAspect: Uint8 {
|
||||||
|
FramebufferObject = 1 << 0,
|
||||||
|
VertexArrayObject = 1 << 1,
|
||||||
|
UniformBuffer = 1 << 2,
|
||||||
|
VertexBuffer = 1 << 3,
|
||||||
|
IndexBuffer = 1 << 4,
|
||||||
|
Viewport = 1 << 5,
|
||||||
|
Scissor = 1 << 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DrawArrayCmd {
|
||||||
GLenum mode = GL_TRIANGLES;
|
GLenum mode = GL_TRIANGLES;
|
||||||
GLint first = 0;
|
GLint first = 0;
|
||||||
GLsizei count = 0;
|
GLsizei count = 0;
|
||||||
const MG_State::GLState::ProgramObject* program = nullptr;
|
|
||||||
const MG_State::GLState::VertexArrayObject* vertexArray = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawElementPayload {
|
struct DrawElementCmd: public DrawArrayCmd {
|
||||||
DrawArrayPayload drawArray;
|
|
||||||
GLenum indexType = GL_UNSIGNED_SHORT;
|
GLenum indexType = GL_UNSIGNED_SHORT;
|
||||||
SizeT indexByteOffset = 0;
|
SizeT indexByteOffset = 0;
|
||||||
GLint baseVertex = 0;
|
GLint baseVertex = 0;
|
||||||
@@ -70,13 +77,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void Initialize();
|
void Initialize();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void QueueClearRequest(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil,
|
void SetupDraw(FrameContext::FrameData& frame, GLenum mode, Flags<DrawSetupAspect> aspects);
|
||||||
Uint drawFboExternalIndex, Bool isDefaultFramebufferTarget);
|
|
||||||
Bool ConsumePendingColorClear(VkClearColorValue& outClearColor);
|
void Clear(GLbitfield mask);
|
||||||
void EnsureFrameRecordingStarted();
|
void DrawArrays(const DrawArrayCmd& payload);
|
||||||
void DrawArrays(const DrawArrayPayload& payload);
|
void DrawElements(const DrawElementCmd& payload);
|
||||||
void DrawElements(const DrawElementPayload& payload);
|
void MultiDrawElements(const Vector<DrawElementCmd>& payloads);
|
||||||
void MultiDrawElements(const Vector<DrawElementPayload>& payloads);
|
|
||||||
void Present();
|
void Present();
|
||||||
|
|
||||||
const PhysicalDevice& GetPhysicalDevice() const;
|
const PhysicalDevice& GetPhysicalDevice() const;
|
||||||
@@ -85,15 +91,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void RecreateSwapchain();
|
void RecreateSwapchain();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PendingClearState {
|
|
||||||
GLbitfield mask = 0;
|
|
||||||
VkClearColorValue color = {{0.0f, 0.0f, 0.0f, 1.0f}};
|
|
||||||
Float depth = 1.0f;
|
|
||||||
Uint32 stencil = 0;
|
|
||||||
Uint drawFboExternalIndex = 0;
|
|
||||||
Bool targetsDefaultFramebuffer = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
NativeWindowType m_window = 0;
|
NativeWindowType m_window = 0;
|
||||||
VulkanRendererConfig m_config;
|
VulkanRendererConfig m_config;
|
||||||
|
|
||||||
@@ -123,6 +120,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
RenderPassEntry* m_activeRenderPass = nullptr;
|
||||||
|
|
||||||
Vector<VkBufferObject> m_frameVertexUploadBuffers;
|
Vector<VkBufferObject> m_frameVertexUploadBuffers;
|
||||||
Vector<VkDeviceSize> m_frameVertexUploadHeads;
|
Vector<VkDeviceSize> m_frameVertexUploadHeads;
|
||||||
Vector<VkBufferObject> m_frameIndexUploadBuffers;
|
Vector<VkBufferObject> m_frameIndexUploadBuffers;
|
||||||
@@ -131,13 +130,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
Uint m_imageIndexAcquired = 0;
|
Uint m_imageIndexAcquired = 0;
|
||||||
FrameContext m_frameContext;
|
FrameContext m_frameContext;
|
||||||
UnorderedMap<Uint64, PendingClearState> m_pendingClears;
|
|
||||||
Bool m_isMainRenderPassActive = false;
|
|
||||||
VkRenderPass m_activeRenderPass = VK_NULL_HANDLE;
|
|
||||||
VkExtent2D m_activeRenderExtent = {0, 0};
|
|
||||||
VkFormat m_activeDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
|
||||||
Bool m_activeRenderTargetIsDefault = true;
|
|
||||||
Uint m_activeDrawFboExternalIndex = 0;
|
|
||||||
|
|
||||||
UniquePtr<PipelineFactory> m_pipelineFactory;
|
UniquePtr<PipelineFactory> m_pipelineFactory;
|
||||||
UniquePtr<ProgramFactory> m_programFactory;
|
UniquePtr<ProgramFactory> m_programFactory;
|
||||||
@@ -160,9 +152,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void CreateSwapchain();
|
void CreateSwapchain();
|
||||||
void CreateCommandPool();
|
void CreateCommandPool();
|
||||||
void CreateFrameContexts();
|
void CreateFrameContexts();
|
||||||
VkPipeline GetOrCreatePipeline(const MG_State::GLState::ProgramObject& program, VkPipelineLayout pipelineLayout,
|
|
||||||
Uint64 vertexInputHash,
|
VkPipeline GetOrCreatePipeline(
|
||||||
const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
GLenum mode,
|
||||||
|
const MG_State::GLState::ProgramObject& program,
|
||||||
|
const MG_State::GLState::VertexArrayObject& vao,
|
||||||
|
const MG_State::GLState::FramebufferObject& drawFbo);
|
||||||
|
|
||||||
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void EndFrameRecordingIfNeeded();
|
void EndFrameRecordingIfNeeded();
|
||||||
@@ -170,9 +166,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void CollectDeferredBufferReleases(Uint32 frameIndex);
|
void CollectDeferredBufferReleases(Uint32 frameIndex);
|
||||||
Bool EnsureFrameUploadBufferCapacity(Uint32 frameIndex, Bool isIndexBuffer, VkDeviceSize requiredEndOffset,
|
Bool EnsureFrameUploadBufferCapacity(Uint32 frameIndex, Bool isIndexBuffer, VkDeviceSize requiredEndOffset,
|
||||||
VkDeviceSize minCapacity, VkBufferUsageFlags usage);
|
VkDeviceSize minCapacity, VkBufferUsageFlags usage);
|
||||||
Bool UploadAndBindVertexStreams(const VertexInputStateFactory::BackendVertexInputState& vertexInputState,
|
Bool UploadAndBindVertexStreams(VkCommandBuffer commandBuffer, const MG_State::GLState::VertexArrayObject& vao);
|
||||||
const DrawArrayPayload& payload, VkCommandBuffer commandBuffer);
|
|
||||||
void ApplyPendingClearsForActiveTarget(VkCommandBuffer commandBuffer, Uint64 drawTargetKey);
|
|
||||||
|
|
||||||
void ShutdownSwapchain();
|
void ShutdownSwapchain();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user