How to upload multiple textures to a shader? #120
-
I'm writing a batched sprite renderer. Each sprite can have a unique texture and a unique sampler. uniform sampler2D u_textures[32]; In OpenGL it's very simple, you just bind all textures you want and upload them as an array of their ids. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
The idea for this was to use const std::uint32_t yourStartBindingSlot = 0;
const std::uint32_t textureSamplerCount = 32;
// Bind all textures consecutively to take advantage of binding multiple textures at once
for (std::uint32_t i = 0; i < textureSamplerCount; ++i) {
layoutDesc.heapBindings.push_back(
LLGL::BindingDescriptor{
/*name:*/ "u_textures",
/*type:*/ LLGL::ResourceType::Texture,
/*bindFlags:*/ LLGL::BindFlags::Sampled,
/*stageFlags:*/ LLGL::StageFlags::FragmentStage,
/*slot:*/ yourStartBindingSlot + i
}
);
}
// Now declare binding slots for all samplers consecutively
for (std::uint32_t i = 0; i < textureSamplerCount; ++i) {
layoutDesc.heapBindings.push_back(
LLGL::BindingDescriptor{
/*name:*/ "", // GL samplers are nameless in LLGL
/*type:*/ LLGL::ResourceType::Sampler,
/*bindFlags:*/ 0, // sampler have no binding flags in LLGL
/*stageFlags:*/ LLGL::StageFlags::FragmentStage,
/*slot:*/ yourStartBindingSlot + i // Same binding slot as for the textures
}
);
}; Now you have to put all your resources into a // Create empty resource heap for your PipelineLayout
LLGL::ResourceHeap* heap = renderer->CreateResourceHeap(myPipelineLayout);
// Place resources in your heap.
// Their indices correspond to the order of your 'heapBindings' entries, not the resource slots!
renderer->WriteResourceHeap(*heap, /*firstDescriptor:*/ 0, { myTex0, myTex1, ..., myTex31 });
renderer->WriteResourceHeap(*heap, /*firstDescriptor:*/ 32, { mySampler0, mySampler1, ..., mySampler31 }); Now you can bind them all at once during your render passes: cmdBuffer->SetResourceHeap(*heap); FWIW: The combination of texture and sampler in GL is really more of a restriction than a feature, but especially mobile drivers prefer them even in Vulkan where you have both combined and separate samplers. This code sample looks like a lot compared to how simple it looks in the GL API, but with an abstraction layer, it's important to separate the native binding slots because the binding models work very differently between the rendering APIs. Vulkan for instance requires unique binding slots for each resource while D3D11 and GL allow shared binding slots across all resources types. I hope this helps, I will try to improve the usability of the |
Beta Was this translation helpful? Give feedback.
The idea for this was to use
BindingDescriptor::arraySize
but this is only half implemented and the documentation also only mentions Vulkan. What you can do is to declare 32 binding descriptors for textures and another 32 for samplers because in LLGL, you have to bind textures and samplers separately to the same binding slot for GL. If you want to take advantage of binding multiple resources at once (like theglBindTextures
function) you can declare those resources in a resource heap, i.e.heapBindings
instead ofbindings
field in your pipeline layout. So in your case, this could look something like this: