mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-10 19:43:23 +09:00
[MG_Backend, MG_Impl] (DirectGLES, Magma): the monolith arm's client fetch bounds
DirectGLES: the client snapshot's baseInstance shift belongs to the backend's emulation, not to the element set. A driver that applies baseInstance itself (UseNativeBaseInstance) must not also receive a shifted pointer - doing both moved instance 0 from element 1 to element 2 and left the instance that reads element 1 outside the snapshot. EmulatedFetchBaseInstance is not declared this early in the file, so the wrapper states the same answer inline. Magma: ResolveIndirectCommandBytes reconciles a GPU-written command block before the callers read it. Every one of them reads the words on the CPU - the per-command expansion, the baseInstance the shader emulation is fed, and the range a client-memory vertex array's upload is bounded by - so a command a compute shader wrote this frame was expanded as the poison the shadow still held, which is no draw at all for glDrawArraysIndirect. Magma: a client-memory INSTANCE-RATE binding is bounded by its instances (baseInstance + (instanceCount - 1) / divisor), not by the vertex range; the upload now covers the union of the two, which is what instances shifted off the front of the array needed.
This commit is contained in:
@@ -4028,7 +4028,29 @@ void main() {
|
||||
// real fetch range. For indexed draws that means scanning the index bytes:
|
||||
// the guessed vertexCount (indexCount + baseVertex) can both truncate draws
|
||||
// whose max index exceeds their index count and over-read below it.
|
||||
const SizeT clientElementBound = resolveDrawElementBound();
|
||||
// AN INSTANCE-RATE BINDING IS BOUNDED BY ITS INSTANCES, not by the vertex range:
|
||||
// it fetches one element per instance, shifted by the draw's baseInstance, so
|
||||
// its last element is baseInstance + (instanceCount - 1) / divisor. The two
|
||||
// bounds are independent and either can exceed the other (an indexed draw
|
||||
// naming element 2^16, or baseInstance 1000 over a three-element array), so
|
||||
// the upload covers their union.
|
||||
SizeT clientElementBound = resolveDrawElementBound();
|
||||
if (vertexInputState.bindings[binding].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE &&
|
||||
drawParams.instanceCount > 0) {
|
||||
Uint32 divisor = 1;
|
||||
for (const auto& divisorEntry : vertexInputState.bindingDivisors) {
|
||||
if (divisorEntry.binding == vertexInputState.bindings[binding].binding) {
|
||||
divisor = divisorEntry.divisor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (divisor > 0) {
|
||||
const Uint64 first = drawParams.firstInstance;
|
||||
const Uint64 last = first + (drawParams.instanceCount - 1) / divisor;
|
||||
clientElementBound =
|
||||
std::max<SizeT>(clientElementBound, static_cast<SizeT>(last + 1));
|
||||
}
|
||||
}
|
||||
BufferSlice slice{};
|
||||
Bool uploaded = false;
|
||||
if (conversion == VertexInputStateFactory::VertexStreamConversion::None) {
|
||||
|
||||
Reference in New Issue
Block a user