mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 07:35:41 +00:00
OpenGLDevice: Work around lack of base_vertex in GLES3.1
This commit is contained in:
parent
e60654de38
commit
344d2ccd5d
|
@ -1014,15 +1014,42 @@ void OpenGLDevice::UnbindPipeline(const OpenGLPipeline* pl)
|
|||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE void OpenGLDevice::SetVertexBufferOffsets(u32 base_vertex)
|
||||
{
|
||||
const OpenGLPipeline::VertexArrayCacheKey& va = m_last_vao->first;
|
||||
const size_t stride = va.vertex_attribute_stride;
|
||||
for (u32 i = 0; i < va.num_vertex_attributes; i++)
|
||||
{
|
||||
glBindVertexBuffer(i, m_vertex_buffer->GetGLBufferId(), base_vertex * stride + va.vertex_attributes[i].offset,
|
||||
static_cast<GLsizei>(stride));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDevice::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
glDrawArrays(m_current_pipeline->GetTopology(), base_vertex, vertex_count);
|
||||
if (glDrawElementsBaseVertex) [[likely]]
|
||||
{
|
||||
glDrawArrays(m_current_pipeline->GetTopology(), base_vertex, vertex_count);
|
||||
return;
|
||||
}
|
||||
|
||||
SetVertexBufferOffsets(base_vertex);
|
||||
glDrawArrays(m_current_pipeline->GetTopology(), 0, vertex_count);
|
||||
}
|
||||
|
||||
void OpenGLDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
if (glDrawElementsBaseVertex) [[likely]]
|
||||
{
|
||||
const void* indices = reinterpret_cast<const void*>(static_cast<uintptr_t>(base_index) * sizeof(u16));
|
||||
glDrawElementsBaseVertex(m_current_pipeline->GetTopology(), index_count, GL_UNSIGNED_SHORT, indices, base_vertex);
|
||||
return;
|
||||
}
|
||||
|
||||
SetVertexBufferOffsets(base_vertex);
|
||||
|
||||
const void* indices = reinterpret_cast<const void*>(static_cast<uintptr_t>(base_index) * sizeof(u16));
|
||||
glDrawElementsBaseVertex(m_current_pipeline->GetTopology(), index_count, GL_UNSIGNED_SHORT, indices, base_vertex);
|
||||
glDrawElements(m_current_pipeline->GetTopology(), index_count, GL_UNSIGNED_SHORT, indices);
|
||||
}
|
||||
|
||||
void OpenGLDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space,
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id);
|
||||
void UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key);
|
||||
|
||||
GLuint LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||
GLuint CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride);
|
||||
void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||
|
||||
|
@ -165,6 +165,8 @@ private:
|
|||
void ApplyDepthState(GPUPipeline::DepthState ds);
|
||||
void ApplyBlendState(GPUPipeline::BlendState bs);
|
||||
|
||||
void SetVertexBufferOffsets(u32 base_vertex);
|
||||
|
||||
std::unique_ptr<GL::Context> m_gl_context;
|
||||
|
||||
std::unique_ptr<OpenGLStreamBuffer> m_vertex_buffer;
|
||||
|
@ -178,12 +180,12 @@ private:
|
|||
GPUFramebufferManager<GLuint, CreateFramebuffer, DestroyFramebuffer> m_framebuffer_manager;
|
||||
|
||||
// VAO cache - fixed max as key
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator m_last_vao = m_vao_cache.cend();
|
||||
GPUPipeline::BlendState m_last_blend_state = {};
|
||||
GPUPipeline::RasterizationState m_last_rasterization_state = {};
|
||||
GPUPipeline::DepthState m_last_depth_state = {};
|
||||
GLuint m_uniform_buffer_alignment = 1;
|
||||
GLuint m_last_program = 0;
|
||||
GLuint m_last_vao = 0;
|
||||
u32 m_last_texture_unit = 0;
|
||||
std::array<std::pair<GLuint, GLuint>, MAX_TEXTURE_SAMPLERS> m_last_samplers = {};
|
||||
GLuint m_last_ssbo = 0;
|
||||
|
|
|
@ -360,7 +360,7 @@ GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig)
|
|||
{
|
||||
glBindAttribLocation(program_id, i,
|
||||
TinyString::from_format("{}{}", semantic_vars[static_cast<u8>(va.semantic.GetValue())],
|
||||
static_cast<u8>(va.semantic_index)));
|
||||
static_cast<u8>(va.semantic_index)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,13 +451,13 @@ void OpenGLDevice::UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key)
|
|||
m_program_cache.erase(it);
|
||||
}
|
||||
|
||||
GLuint OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key)
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key)
|
||||
{
|
||||
auto it = m_vao_cache.find(key);
|
||||
OpenGLPipeline::VertexArrayCache::iterator it = m_vao_cache.find(key);
|
||||
if (it != m_vao_cache.end())
|
||||
{
|
||||
it->second.reference_count++;
|
||||
return it->second.vao_id;
|
||||
return it;
|
||||
}
|
||||
|
||||
OpenGLPipeline::VertexArrayCacheItem item;
|
||||
|
@ -465,11 +465,10 @@ GLuint OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& k
|
|||
CreateVAO(std::span<const GPUPipeline::VertexAttribute>(key.vertex_attributes, key.num_vertex_attributes),
|
||||
key.vertex_attribute_stride);
|
||||
if (item.vao_id == 0)
|
||||
return 0;
|
||||
return m_vao_cache.cend();
|
||||
|
||||
item.reference_count = 1;
|
||||
m_vao_cache.emplace(key, item);
|
||||
return item.vao_id;
|
||||
return m_vao_cache.emplace(key, item).first;
|
||||
}
|
||||
|
||||
GLuint OpenGLDevice::CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride)
|
||||
|
@ -518,7 +517,8 @@ GLuint OpenGLDevice::CreateVAO(std::span<const GPUPipeline::VertexAttribute> att
|
|||
glVertexAttribPointer(i, va.components, m.type, m.normalized, stride, ptr);
|
||||
}
|
||||
|
||||
glBindVertexArray(m_last_vao);
|
||||
if (m_last_vao != m_vao_cache.cend())
|
||||
glBindVertexArray(m_last_vao->second.vao_id);
|
||||
|
||||
return vao;
|
||||
}
|
||||
|
@ -531,9 +531,9 @@ void OpenGLDevice::UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key)
|
|||
if ((--it->second.reference_count) > 0)
|
||||
return;
|
||||
|
||||
if (m_last_vao == it->second.vao_id)
|
||||
if (m_last_vao == it)
|
||||
{
|
||||
m_last_vao = 0;
|
||||
m_last_vao = m_vao_cache.cend();
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
@ -541,8 +541,9 @@ void OpenGLDevice::UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key)
|
|||
m_vao_cache.erase(it);
|
||||
}
|
||||
|
||||
OpenGLPipeline::OpenGLPipeline(const ProgramCacheKey& key, GLuint program, GLuint vao, const RasterizationState& rs,
|
||||
const DepthState& ds, const BlendState& bs, GLenum topology)
|
||||
OpenGLPipeline::OpenGLPipeline(const ProgramCacheKey& key, GLuint program, VertexArrayCache::const_iterator vao,
|
||||
const RasterizationState& rs, const DepthState& ds, const BlendState& bs,
|
||||
GLenum topology)
|
||||
: m_key(key), m_program(program), m_vao(vao), m_blend_state(bs), m_rasterization_state(rs), m_depth_state(ds),
|
||||
m_topology(topology)
|
||||
{
|
||||
|
@ -572,8 +573,8 @@ std::unique_ptr<GPUPipeline> OpenGLDevice::CreatePipeline(const GPUPipeline::Gra
|
|||
if (program_id == 0)
|
||||
return {};
|
||||
|
||||
const GLuint vao_id = LookupVAOCache(pkey.va_key);
|
||||
if (vao_id == 0)
|
||||
const OpenGLPipeline::VertexArrayCache::const_iterator vao = LookupVAOCache(pkey.va_key);
|
||||
if (vao == m_vao_cache.cend())
|
||||
{
|
||||
UnrefProgram(pkey);
|
||||
return {};
|
||||
|
@ -586,7 +587,7 @@ std::unique_ptr<GPUPipeline> OpenGLDevice::CreatePipeline(const GPUPipeline::Gra
|
|||
GL_TRIANGLE_STRIP, // TriangleStrips
|
||||
}};
|
||||
|
||||
return std::unique_ptr<GPUPipeline>(new OpenGLPipeline(pkey, program_id, vao_id, config.rasterization, config.depth,
|
||||
return std::unique_ptr<GPUPipeline>(new OpenGLPipeline(pkey, program_id, vao, config.rasterization, config.depth,
|
||||
config.blend, primitives[static_cast<u8>(config.primitive)]));
|
||||
}
|
||||
|
||||
|
@ -716,7 +717,7 @@ void OpenGLDevice::SetPipeline(GPUPipeline* pipeline)
|
|||
if (m_last_vao != P->GetVAO())
|
||||
{
|
||||
m_last_vao = P->GetVAO();
|
||||
glBindVertexArray(m_last_vao);
|
||||
glBindVertexArray(m_last_vao->second.vao_id);
|
||||
}
|
||||
if (m_last_program != P->GetProgram())
|
||||
{
|
||||
|
|
|
@ -97,7 +97,7 @@ public:
|
|||
~OpenGLPipeline() override;
|
||||
|
||||
ALWAYS_INLINE GLuint GetProgram() const { return m_program; }
|
||||
ALWAYS_INLINE GLuint GetVAO() const { return m_vao; }
|
||||
ALWAYS_INLINE VertexArrayCache::const_iterator GetVAO() const { return m_vao; }
|
||||
ALWAYS_INLINE const RasterizationState& GetRasterizationState() const { return m_rasterization_state; }
|
||||
ALWAYS_INLINE const DepthState& GetDepthState() const { return m_depth_state; }
|
||||
ALWAYS_INLINE const BlendState& GetBlendState() const { return m_blend_state; }
|
||||
|
@ -106,12 +106,12 @@ public:
|
|||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
private:
|
||||
OpenGLPipeline(const ProgramCacheKey& key, GLuint program, GLuint vao, const RasterizationState& rs,
|
||||
const DepthState& ds, const BlendState& bs, GLenum topology);
|
||||
OpenGLPipeline(const ProgramCacheKey& key, GLuint program, VertexArrayCache::const_iterator vao,
|
||||
const RasterizationState& rs, const DepthState& ds, const BlendState& bs, GLenum topology);
|
||||
|
||||
ProgramCacheKey m_key;
|
||||
VertexArrayCache::const_iterator m_vao;
|
||||
GLuint m_program;
|
||||
GLuint m_vao;
|
||||
BlendState m_blend_state;
|
||||
RasterizationState m_rasterization_state;
|
||||
DepthState m_depth_state;
|
||||
|
|
Loading…
Reference in a new issue