Skip to content

Commit 64a7c91

Browse files
committed
Added support for gl_InstanceIndex in OpenGL backend
Warning: works only in not indirect drawscalls!
1 parent 1cbef4e commit 64a7c91

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

include/nbl/asset/ICPUPipelineLayout.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ class ICPUPipelineLayout : public IAsset, public IPipelineLayout<ICPUDescriptorS
3434
void setDescriptorSetLayout(uint32_t _set, core::smart_refctd_ptr<ICPUDescriptorSetLayout>&& _dslayout)
3535
{
3636
assert(!isImmutable_debug());
37-
m_descSetLayouts[_set] = std::move(_dslayout);
37+
assert(_set < DESCRIPTOR_SET_COUNT);
38+
m_descSetLayouts[_set] = std::move(_dslayout);
39+
}
40+
41+
void setPushConstantRanges(core::smart_refctd_dynamic_array<SPushConstantRange>&& _ranges)
42+
{
43+
assert(!isImmutable_debug());
44+
m_pushConstantRanges = std::move(_ranges);
3845
}
3946

4047
core::smart_refctd_ptr<IAsset> clone(uint32_t _depth = ~0u) const override

source/Nabla/COpenGLDriver.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,7 @@ void COpenGLDriver::drawMeshBuffer(const IGPUMeshBuffer* mb)
18281828
return;
18291829

18301830
found->updateNextState_vertexInput(mb->getVertexBufferBindings(), mb->getIndexBufferBinding().buffer.get(), found->nextState.vertexInputParams.indirectDrawBuf.get(), found->nextState.vertexInputParams.parameterBuf.get());
1831+
auto* pipeline = found->nextState.pipeline.graphics.pipeline.get();
18311832

18321833
CNullDriver::drawMeshBuffer(mb);
18331834

@@ -1851,6 +1852,10 @@ void COpenGLDriver::drawMeshBuffer(const IGPUMeshBuffer* mb)
18511852
}
18521853
}
18531854

1855+
const GLint baseInstance = static_cast<GLint>(mb->getBaseInstance());
1856+
// if GL_ARB_shader_draw_parameters is present, gl_BaseInstanceARB is used for workaround instead
1857+
if (!FeatureAvailable[NBL_ARB_shader_draw_parameters])
1858+
pipeline->setBaseInstanceUniform(found->ID, baseInstance);
18541859

18551860
found->flushStateGraphics(GSB_ALL);
18561861

@@ -1861,10 +1866,10 @@ void COpenGLDriver::drawMeshBuffer(const IGPUMeshBuffer* mb)
18611866
if (indexSize) {
18621867
static_assert(sizeof(mb->getIndexBufferBinding().offset) == sizeof(void*), "Might break without this requirement");
18631868
const void* const idxBufOffset = reinterpret_cast<void*>(mb->getIndexBufferBinding().offset);
1864-
extGlDrawElementsInstancedBaseVertexBaseInstance(primType, mb->getIndexCount(), indexSize, idxBufOffset, mb->getInstanceCount(), mb->getBaseVertex(), mb->getBaseInstance());
1869+
extGlDrawElementsInstancedBaseVertexBaseInstance(primType, mb->getIndexCount(), indexSize, idxBufOffset, mb->getInstanceCount(), mb->getBaseVertex(), baseInstance);
18651870
}
18661871
else
1867-
extGlDrawArraysInstancedBaseInstance(primType, mb->getBaseVertex(), mb->getIndexCount(), mb->getInstanceCount(), mb->getBaseInstance());
1872+
extGlDrawArraysInstancedBaseInstance(primType, mb->getBaseVertex(), mb->getIndexCount(), mb->getInstanceCount(), baseInstance);
18681873
}
18691874

18701875

src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ layout (location = 3) out vec2 UV;
4040
#include <nbl/builtin/glsl/utils/common.glsl>
4141
#include <nbl/builtin/glsl/utils/transform.glsl>
4242
43-
layout (push_constant) uniform Block {
44-
uint instDataOffset;
45-
} PC;
46-
4743
#ifndef _NBL_VERT_SET1_BINDINGS_DEFINED_
4844
#define _NBL_VERT_SET1_BINDINGS_DEFINED_
4945
layout (set = 1, binding = 0, row_major, std140) uniform UBO {
@@ -59,7 +55,7 @@ layout (set = 0, binding = 5, row_major, std430) readonly restrict buffer InstDa
5955
6056
void main()
6157
{
62-
uint instIx = PC.instDataOffset+gl_InstanceIndex;
58+
uint instIx = gl_InstanceIndex;
6359
mat4x3 tform = InstData.data[instIx].tform;
6460
mat4 mvp = nbl_glsl_pseudoMul4x4with4x3(CamData.params.MVP, tform);
6561
gl_Position = nbl_glsl_pseudoMul4x4with3x1(mvp, vPosition);
@@ -289,6 +285,8 @@ vec3 nbl_computeLighting(inout nbl_glsl_IsotropicViewSurfaceInteraction out_inte
289285
}
290286
#endif
291287
288+
#ifndef _NBL_FRAG_MAIN_DEFINED_
289+
#define _NBL_FRAG_MAIN_DEFINED_
292290
void main()
293291
{
294292
mat2 dUV = mat2(dFdx(UV),dFdy(UV));
@@ -309,6 +307,7 @@ void main()
309307
310308
OutColor = vec4(color, 1.0);
311309
}
310+
#endif
312311
)";
313312

314313
_NBL_STATIC_INLINE_CONSTEXPR const char* VERTEX_SHADER_CACHE_KEY = "nbl/builtin/specialized_shader/loaders/mitsuba_xml/default";
@@ -692,11 +691,6 @@ static core::smart_refctd_ptr<asset::ICPUImage> createBlendWeightImage(const ass
692691

693692
core::smart_refctd_ptr<asset::ICPUPipelineLayout> CMitsubaLoader::createPipelineLayout(asset::IAssetManager* _manager, asset::ICPUVirtualTexture* _vt)
694693
{
695-
SPushConstantRange pcrng;
696-
pcrng.offset = 0u;
697-
pcrng.size = sizeof(uint32_t);//instance data offset
698-
pcrng.stageFlags = static_cast<asset::ISpecializedShader::E_SHADER_STAGE>(asset::ISpecializedShader::ESS_FRAGMENT | asset::ISpecializedShader::ESS_VERTEX);
699-
700694
core::smart_refctd_ptr<ICPUDescriptorSetLayout> ds0layout; // needs to builtin and cached statically
701695
{
702696
auto sizes = _vt->getDSlayoutBindings(nullptr, nullptr);
@@ -739,7 +733,7 @@ core::smart_refctd_ptr<asset::ICPUPipelineLayout> CMitsubaLoader::createPipeline
739733
}
740734
auto ds1layout = getBuiltinAsset<ICPUDescriptorSetLayout, IAsset::ET_DESCRIPTOR_SET_LAYOUT>("nbl/builtin/descriptor_set_layout/basic_view_parameters", _manager);
741735

742-
return core::make_smart_refctd_ptr<asset::ICPUPipelineLayout>(&pcrng, &pcrng+1, std::move(ds0layout), std::move(ds1layout), nullptr, nullptr);
736+
return core::make_smart_refctd_ptr<asset::ICPUPipelineLayout>(nullptr, nullptr, std::move(ds0layout), std::move(ds1layout), nullptr, nullptr);
743737
}
744738

745739
CMitsubaLoader::CMitsubaLoader(asset::IAssetManager* _manager) : asset::IAssetLoader(), m_manager(_manager)
@@ -1761,7 +1755,7 @@ inline core::smart_refctd_ptr<asset::ICPUDescriptorSet> CMitsubaLoader::createDS
17611755
for (uint32_t i = 0u; i < mesh->getMeshBufferCount(); ++i)
17621756
{
17631757
auto* mb = mesh->getMeshBuffer(i);
1764-
reinterpret_cast<uint32_t*>(mb->getPushConstantsDataPtr())[0] = instDataOffset; // use base instance!
1758+
mb->setBaseInstance(instDataOffset);
17651759
}
17661760
}
17671761
#ifdef DEBUG_MITSUBA_LOADER

src/nbl/video/COpenGLRenderpassIndependentPipeline.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class COpenGLRenderpassIndependentPipeline final : public IGPURenderpassIndepend
3636
_vertexInputParams, _blendParams, _primAsmParams, _rasterParams
3737
),
3838
IOpenGLPipeline(_ctxCount, _ctxID, _GLnames, _binaries),
39-
m_stagePresenceMask(0u)
39+
m_stagePresenceMask(0u),
40+
m_baseInstanceUniformIDs(core::make_refctd_dynamic_array<decltype(m_baseInstanceUniformIDs)>(_ctxCount))
4041
{
4142
static_assert(asset::SVertexInputParams::MAX_ATTR_BUF_BINDING_COUNT == asset::SVertexInputParams::MAX_VERTEX_ATTRIB_COUNT, "This code below has to be divided into 2 loops");
4243
static_assert(asset::EF_UNKNOWN <= 0xffu, "All E_FORMAT values must fit in 1 byte or hash falls apart");
@@ -64,6 +65,30 @@ class COpenGLRenderpassIndependentPipeline final : public IGPURenderpassIndepend
6465
}
6566
}
6667

68+
// should be called in case of absence of GL_ARB_shader_draw_parameters only
69+
void setBaseInstanceUniform(uint32_t _ctxID, GLint _baseInstance) const
70+
{
71+
// only this function touches this uniform
72+
constexpr const char* SPIRV_CROSS_BaseInstanceUniformName = "SPIRV_Cross_BaseInstance";
73+
74+
GLint& value = (*m_baseInstanceUniformIDs)[_ctxID].cache;
75+
if (value == _baseInstance)
76+
return;
77+
78+
const GLuint programID = getShaderGLnameForCtx(ESSI_VERTEX_SHADER_IX, _ctxID);
79+
GLint& uid = (*m_baseInstanceUniformIDs)[_ctxID].id;
80+
if (uid == -1)
81+
{
82+
uid = COpenGLExtensionHandler::extGlGetUniformLocation(programID, SPIRV_CROSS_BaseInstanceUniformName);
83+
}
84+
if (uid == -1)
85+
return;
86+
87+
value = _baseInstance;
88+
89+
COpenGLExtensionHandler::extGlProgramUniform1iv(programID, uid, 1u, &value);
90+
}
91+
6792
uint32_t getStagePresenceMask() const { return m_stagePresenceMask; }
6893

6994
GLuint getShaderGLnameForCtx(uint32_t _stageIx, uint32_t _ctxID) const
@@ -290,6 +315,16 @@ class COpenGLRenderpassIndependentPipeline final : public IGPURenderpassIndepend
290315
SVAOHash m_vaoHashval;
291316
uint32_t m_stagePresenceMask;
292317
mutable uint32_t m_lastUpdateStamp[SHADER_STAGE_COUNT];
318+
319+
// needed for spirv-cross-based workaround of GL's behaviour of gl_InstanceID
320+
struct SBaseInstance
321+
{
322+
GLint cache = 0;
323+
GLint id = -1;
324+
};
325+
// per-context ID of SPIRV_Cross_BaseInstance uniform
326+
// (only present in case of absence of GL_ARB_shader_draw_parameters)
327+
mutable core::smart_refctd_dynamic_array<SBaseInstance> m_baseInstanceUniformIDs;
293328
};
294329

295330
}

0 commit comments

Comments
 (0)