mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (Diligent/PSO, MG_State/Buffer): implement GL_TRIANGLE_FAN emulation, fixing sky
This commit is contained in:
@@ -23,6 +23,7 @@ namespace MG_Diligent {
|
||||
MG_Global::unordered_map<GLuint, GLProgramInfo> g_ProgramMap;
|
||||
MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
|
||||
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
|
||||
Diligent::IBuffer* g_TriangleFanIndexBuffer = nullptr;
|
||||
GLuint g_NextResourceId = 0;
|
||||
bool IsInRenderPass = false;
|
||||
bool initialized = false;
|
||||
@@ -101,7 +102,8 @@ namespace MG_Diligent {
|
||||
uint64_t PipelineStateManager::CalculateStateHash(
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo) {
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology) {
|
||||
size_t hash = 0;
|
||||
|
||||
auto& capabilities = commonState.capabilities;
|
||||
@@ -121,6 +123,7 @@ namespace MG_Diligent {
|
||||
hash_combine(hash, commonState.depthMask);
|
||||
hash_combine(hash, capabilities[GL_DEPTH_TEST]);
|
||||
|
||||
hash_combine(hash, primitiveTopology);
|
||||
hash_combine(hash, 0); // TODO: Cull Face Mode
|
||||
hash_combine(hash, capabilities[GL_CULL_FACE]);
|
||||
hash_combine(hash, capabilities[GL_STENCIL_TEST]);
|
||||
@@ -168,7 +171,8 @@ namespace MG_Diligent {
|
||||
GLProgramInfo &programInfo,
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo) {
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology) {
|
||||
PSOCreateInfo.PSODesc.Name = "Program_PSO";
|
||||
PSOCreateInfo.PSODesc.PipelineType = Diligent::PIPELINE_TYPE_GRAPHICS;
|
||||
|
||||
@@ -199,7 +203,7 @@ namespace MG_Diligent {
|
||||
PSOCreateInfo.GraphicsPipeline.pRenderPass = g_FramebufferMap[0].pRenderPass; // Default render pass
|
||||
}
|
||||
|
||||
PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = GLPrimitiveTopologyToDiligent(primitiveTopology);
|
||||
|
||||
if (fbInfo.pRenderPass) {
|
||||
PSOCreateInfo.GraphicsPipeline.NumRenderTargets = 0;
|
||||
@@ -314,8 +318,9 @@ namespace MG_Diligent {
|
||||
GLProgramInfo &programInfo,
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo) {
|
||||
uint64_t currentStateHash = CalculateStateHash(commonState, vaState, fbInfo);
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology) {
|
||||
uint64_t currentStateHash = CalculateStateHash(commonState, vaState, fbInfo, primitiveTopology);
|
||||
|
||||
if (programInfo.pPipelineState &&
|
||||
programInfo.psoStateHash == currentStateHash &&
|
||||
@@ -360,7 +365,7 @@ namespace MG_Diligent {
|
||||
MG_Diligent::BuildInputLayout(program, vaState, programInfo.inputLayout);
|
||||
|
||||
Diligent::GraphicsPipelineStateCreateInfo PSOCreateInfo;
|
||||
ConfigurePSO(PSOCreateInfo, programInfo, commonState, vaState, fbInfo);
|
||||
ConfigurePSO(PSOCreateInfo, programInfo, commonState, vaState, fbInfo, primitiveTopology);
|
||||
|
||||
MG_Util::Debug::LogD("Dumping PSOCreateInfo for program %u:", program);
|
||||
MG_Util::Debug::LogD(" PSODesc.Name: %s", PSOCreateInfo.PSODesc.Name);
|
||||
|
||||
@@ -56,6 +56,23 @@ namespace MG_Diligent {
|
||||
|
||||
extern MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
|
||||
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
|
||||
extern Diligent::IBuffer* g_TriangleFanIndexBuffer;
|
||||
|
||||
inline Diligent::PRIMITIVE_TOPOLOGY GLPrimitiveTopologyToDiligent(GLenum Topology)
|
||||
{
|
||||
switch (Topology)
|
||||
{
|
||||
case GL_TRIANGLE_STRIP:
|
||||
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
case GL_TRIANGLES:
|
||||
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
case GL_TRIANGLE_FAN:
|
||||
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
// TODO: Handle other topologies
|
||||
default:
|
||||
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
class PipelineStateManager {
|
||||
private:
|
||||
@@ -83,7 +100,8 @@ namespace MG_Diligent {
|
||||
GLProgramInfo &programInfo,
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo);
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology);
|
||||
|
||||
void MarkPSODirty(GLuint program);
|
||||
|
||||
@@ -191,14 +209,16 @@ namespace MG_Diligent {
|
||||
uint64_t CalculateStateHash(
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo);
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology);
|
||||
|
||||
void ConfigurePSO(
|
||||
Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo,
|
||||
GLProgramInfo &programInfo,
|
||||
CommonState &commonState,
|
||||
VertexArrayState &vaState,
|
||||
GLFramebufferInfo& fbInfo);
|
||||
GLFramebufferInfo& fbInfo,
|
||||
GLenum primitiveTopology);
|
||||
|
||||
void ConfigureResourceLayout(
|
||||
Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo,
|
||||
|
||||
@@ -411,7 +411,22 @@ namespace MG_GL::GL {
|
||||
}
|
||||
}
|
||||
|
||||
void PrepareForDraw() {
|
||||
template<typename T>
|
||||
void generate_triangle_fan_indices(std::vector<uint8_t>& out_data, const void* in_indices, size_t count) {
|
||||
const auto* pIn = static_cast<const T*>(in_indices);
|
||||
std::vector<T> new_indices;
|
||||
new_indices.reserve((count - 2) * 3);
|
||||
T i0 = pIn[0];
|
||||
for (size_t i = 1; i < count - 1; ++i) {
|
||||
new_indices.push_back(i0);
|
||||
new_indices.push_back(pIn[i]);
|
||||
new_indices.push_back(pIn[i+1]);
|
||||
}
|
||||
out_data.resize(new_indices.size() * sizeof(T));
|
||||
memcpy(out_data.data(), new_indices.data(), out_data.size());
|
||||
}
|
||||
|
||||
void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum type, const void*& pIndices) {
|
||||
if (MG_Diligent::IsInRenderPass) {
|
||||
MG_Util::Debug::LogD("Ending current render pass.");
|
||||
MG_Diligent::g_pContext->EndRenderPass();
|
||||
@@ -444,7 +459,8 @@ namespace MG_GL::GL {
|
||||
programInfo,
|
||||
*MG_State_T::commonState,
|
||||
*MG_State_T::vertexArrayState,
|
||||
fbInfo
|
||||
fbInfo,
|
||||
mode
|
||||
);
|
||||
|
||||
if (!programInfo.pPipelineState) {
|
||||
@@ -473,7 +489,6 @@ namespace MG_GL::GL {
|
||||
return;
|
||||
}
|
||||
|
||||
// for (const auto& [attribIndex, attrib] : pVAO->attribs) {
|
||||
for (uint32_t attribIndex = 0; attribIndex < MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS; ++attribIndex) {
|
||||
const auto& attrib = pVAO->attribs[attribIndex];
|
||||
if (!attrib.enabled || attrib.buffer == 0) continue;
|
||||
@@ -507,7 +522,67 @@ namespace MG_GL::GL {
|
||||
}
|
||||
}
|
||||
|
||||
if (pVAO->elementBuffer != 0) {
|
||||
if (mode == GL_TRIANGLE_FAN)
|
||||
{
|
||||
if (*pCount < 3) return;
|
||||
|
||||
const void* pOriginalIndices = nullptr;
|
||||
if (pVAO->elementBuffer != 0)
|
||||
{
|
||||
auto& bufferObj = MG_State_T::bufferState->buffers_[pVAO->elementBuffer];
|
||||
pOriginalIndices = bufferObj.data.data() + reinterpret_cast<uintptr_t>(pIndices);
|
||||
}
|
||||
else
|
||||
{
|
||||
pOriginalIndices = pIndices;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> newIndexData;
|
||||
switch(type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
generate_triangle_fan_indices<uint8_t>(newIndexData, pOriginalIndices, *pCount);
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
generate_triangle_fan_indices<uint16_t>(newIndexData, pOriginalIndices, *pCount);
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
generate_triangle_fan_indices<uint32_t>(newIndexData, pOriginalIndices, *pCount);
|
||||
break;
|
||||
default:
|
||||
MG_Util::Debug::LogE("Unsupported index type for triangle fan conversion: %X", type);
|
||||
return;
|
||||
}
|
||||
|
||||
*pCount = (static_cast<GLsizei>(*pCount) - 2) * 3;
|
||||
pIndices = nullptr;
|
||||
|
||||
if (!MG_Diligent::g_TriangleFanIndexBuffer || MG_Diligent::g_TriangleFanIndexBuffer->GetDesc().Size < newIndexData.size())
|
||||
{
|
||||
if (MG_Diligent::g_TriangleFanIndexBuffer)
|
||||
MG_Diligent::g_TriangleFanIndexBuffer->Release();
|
||||
|
||||
Diligent::BufferDesc BuffDesc;
|
||||
BuffDesc.Name = "Triangle Fan Temp Index Buffer";
|
||||
BuffDesc.Size = newIndexData.size();
|
||||
BuffDesc.Usage = Diligent::USAGE_DYNAMIC;
|
||||
BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER;
|
||||
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
|
||||
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &MG_Diligent::g_TriangleFanIndexBuffer);
|
||||
}
|
||||
|
||||
if (MG_Diligent::g_TriangleFanIndexBuffer)
|
||||
{
|
||||
void* pMappedData = nullptr;
|
||||
MG_Diligent::g_pContext->MapBuffer(MG_Diligent::g_TriangleFanIndexBuffer, Diligent::MAP_WRITE, Diligent::MAP_FLAG_DISCARD, pMappedData);
|
||||
if (pMappedData)
|
||||
{
|
||||
memcpy(pMappedData, newIndexData.data(), newIndexData.size());
|
||||
MG_Diligent::g_pContext->UnmapBuffer(MG_Diligent::g_TriangleFanIndexBuffer, Diligent::MAP_WRITE);
|
||||
}
|
||||
MG_Diligent::g_pContext->SetIndexBuffer(MG_Diligent::g_TriangleFanIndexBuffer, 0, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
}
|
||||
}
|
||||
else if (pVAO->elementBuffer != 0) {
|
||||
GLuint buffer = pVAO->elementBuffer;
|
||||
auto& bufferObj = MG_State_T::bufferState->buffers_[buffer];
|
||||
|
||||
@@ -534,6 +609,10 @@ namespace MG_GL::GL {
|
||||
MG_Util::Debug::LogE("Failed to create dynamic index buffer %u", buffer);
|
||||
}
|
||||
}
|
||||
if (pBuffer)
|
||||
{
|
||||
MG_Diligent::g_pContext->SetIndexBuffer(pBuffer, 0, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
}
|
||||
}
|
||||
|
||||
// Update data for all dynamic buffers
|
||||
@@ -621,26 +700,22 @@ namespace MG_GL::GL {
|
||||
}
|
||||
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
||||
PrepareForDraw();
|
||||
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||
if (pVAO->elementBuffer != 0) {
|
||||
GLuint buffer = pVAO->elementBuffer;
|
||||
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||
if (it != MG_Diligent::g_BufferMap.end() && it->second) {
|
||||
auto offset = reinterpret_cast<uintptr_t>(indices);
|
||||
|
||||
MG_Diligent::g_pContext->SetIndexBuffer(
|
||||
it->second,
|
||||
offset,
|
||||
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
|
||||
);
|
||||
}
|
||||
}
|
||||
const void* pIndices = indices;
|
||||
PrepareForDraw(mode, &count, type, pIndices);
|
||||
|
||||
Diligent::DrawIndexedAttribs drawAttrs;
|
||||
drawAttrs.NumIndices = count;
|
||||
drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL;
|
||||
drawAttrs.IndexType = ConvertGLTypeToDiligent(type);
|
||||
|
||||
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||
if (pIndices != nullptr && pVAO != nullptr && pVAO->elementBuffer != 0) {
|
||||
size_t indexSize = 1;
|
||||
if (drawAttrs.IndexType == Diligent::VT_UINT16) indexSize = 2;
|
||||
else if (drawAttrs.IndexType == Diligent::VT_UINT32) indexSize = 4;
|
||||
drawAttrs.FirstIndexLocation = static_cast<Diligent::Uint32>(reinterpret_cast<uintptr_t>(pIndices) / indexSize);
|
||||
}
|
||||
|
||||
MG_Util::Debug::LogD("DrawIndexedAttribs Dump:");
|
||||
MG_Util::Debug::LogD(" NumIndices: %u", drawAttrs.NumIndices);
|
||||
MG_Util::Debug::LogD(" IndexType: %d", drawAttrs.IndexType);
|
||||
@@ -708,8 +783,9 @@ namespace MG_GL::GL {
|
||||
};
|
||||
|
||||
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount) {
|
||||
PrepareForDraw();
|
||||
|
||||
return;
|
||||
// PrepareForDraw();
|
||||
|
||||
if (MG_Diligent::IsInRenderPass) {
|
||||
MG_Util::Debug::LogD("Ending current render pass.");
|
||||
MG_Diligent::g_pContext->EndRenderPass();
|
||||
@@ -843,7 +919,8 @@ namespace MG_GL::GL {
|
||||
}
|
||||
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex) {
|
||||
PrepareForDraw();
|
||||
return;
|
||||
// PrepareForDraw();
|
||||
|
||||
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||
Diligent::IBuffer* pIndexBuffer = nullptr;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace MG_GL::GL {
|
||||
bool IsSamplerType(GLenum type);
|
||||
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
|
||||
void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum type, const void*& pIndices);
|
||||
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
|
||||
Reference in New Issue
Block a user