OpenGLES: baseVertex, baseInstance workaround.
Use the Tint shader workaround to add baseVertex to gl_BaseVertex.
Offset the pointer passed to glVertexAttrib[I]Pointer() by baseVertex
or firstInstance, depending on buffer step mode.
Split the BaseVertex end2end test into two, since negative BaseVertex
is problematic on some platforms.
Remove all the other codepaths; always use emulation for now.
Remove all dependencies on the GL_ANGLE_base_vertex_base_instance extension.
Change-Id: I8965c983ccd5588af28ba88b8e1d0d519b4422cc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/190460
Commit-Queue: Stephen White <senorblanco@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/generator/templates/opengl/OpenGLFunctionsBase.cpp b/generator/templates/opengl/OpenGLFunctionsBase.cpp
index 261f0fb..5789fcc 100644
--- a/generator/templates/opengl/OpenGLFunctionsBase.cpp
+++ b/generator/templates/opengl/OpenGLFunctionsBase.cpp
@@ -61,15 +61,6 @@
}
{% endfor %}
- // GL_ANGLE_base_vertex_base_instance
- // See crbug.com/dawn/1715 for why this is embedded
- if (IsGLExtensionSupported("GL_ANGLE_base_vertex_base_instance")) {
- DAWN_TRY(LoadProc(getProc, &DrawArraysInstancedBaseInstanceANGLE, "glDrawArraysInstancedBaseInstanceANGLE"));
- DAWN_TRY(LoadProc(getProc, &DrawElementsInstancedBaseVertexBaseInstanceANGLE, "glDrawElementsInstancedBaseVertexBaseInstanceANGLE"));
- DAWN_TRY(LoadProc(getProc, &MultiDrawArraysInstancedBaseInstanceANGLE, "glMultiDrawArraysInstancedBaseInstanceANGLE"));
- DAWN_TRY(LoadProc(getProc, &MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, "glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE"));
- }
-
return {};
}
#endif
diff --git a/generator/templates/opengl/OpenGLFunctionsBase.h b/generator/templates/opengl/OpenGLFunctionsBase.h
index 0096a37..0f8b01f 100644
--- a/generator/templates/opengl/OpenGLFunctionsBase.h
+++ b/generator/templates/opengl/OpenGLFunctionsBase.h
@@ -46,13 +46,6 @@
{% endfor%}
- // GL_ANGLE_base_vertex_base_instance
- // See crbug.com/dawn/1715 for why this is embedded
- PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC DrawArraysInstancedBaseInstanceANGLE = nullptr;
- PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC DrawElementsInstancedBaseVertexBaseInstanceANGLE = nullptr;
- PFNGLMULTIDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC MultiDrawArraysInstancedBaseInstanceANGLE = nullptr;
- PFNGLMULTIDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE = nullptr;
-
bool IsGLExtensionSupported(const char* extension) const;
protected:
diff --git a/generator/templates/opengl/opengl_platform.h b/generator/templates/opengl/opengl_platform.h
index c51363d..d9bfe3e 100644
--- a/generator/templates/opengl/opengl_platform.h
+++ b/generator/templates/opengl/opengl_platform.h
@@ -84,11 +84,4 @@
{% endfor%}
-// GL_ANGLE_base_vertex_base_instance
-// See crbug.com/dawn/1715 for why this is embedded
-using PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount, GLuint baseInstance);
-using PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei instanceCount, GLint baseVertex, GLuint baseInstance);
-using PFNGLMULTIDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, const GLint * firsts, const GLsizei * counts, const GLsizei * instanceCounts, const GLuint * baseInstances, GLsizei drawcount);
-using PFNGLMULTIDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, const GLsizei * counts, GLenum type, const GLvoid *const* indices, const GLsizei * instanceCounts, const GLint * baseVertices, const GLuint * baseInstances, GLsizei drawcount);
-
#undef DAWN_GL_APIENTRY
diff --git a/src/dawn/native/opengl/CommandBufferGL.cpp b/src/dawn/native/opengl/CommandBufferGL.cpp
index cf77e8a..d5e35d2 100644
--- a/src/dawn/native/opengl/CommandBufferGL.cpp
+++ b/src/dawn/native/opengl/CommandBufferGL.cpp
@@ -184,7 +184,17 @@
mLastPipeline = pipeline;
}
- void Apply(const OpenGLFunctions& gl) {
+ void Apply(const OpenGLFunctions& gl, int32_t baseVertex, uint32_t firstInstance) {
+ if (mBaseVertex != baseVertex) {
+ mBaseVertex = baseVertex;
+ mDirtyVertexBuffers |= mLastPipeline->GetVertexBuffersUsedAsVertexBuffer();
+ }
+
+ if (mFirstInstance != firstInstance) {
+ mFirstInstance = firstInstance;
+ mDirtyVertexBuffers |= mLastPipeline->GetVertexBuffersUsedAsInstanceBuffer();
+ }
+
if (mIndexBufferDirty && mIndexBuffer != nullptr) {
gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->GetHandle());
mIndexBufferDirty = false;
@@ -198,9 +208,15 @@
GLuint attribIndex = static_cast<GLuint>(static_cast<uint8_t>(location));
GLuint buffer = mVertexBuffers[slot]->GetHandle();
- uint64_t offset = mVertexBufferOffsets[slot];
+ intptr_t offset = mVertexBufferOffsets[slot];
const VertexBufferInfo& vertexBuffer = mLastPipeline->GetVertexBuffer(slot);
+
+ if (vertexBuffer.stepMode == wgpu::VertexStepMode::Vertex) {
+ offset += mBaseVertex * vertexBuffer.arrayStride;
+ } else if (vertexBuffer.stepMode == wgpu::VertexStepMode::Instance) {
+ offset += mFirstInstance * vertexBuffer.arrayStride;
+ }
uint32_t components = GetVertexFormatInfo(attribute.format).componentCount;
GLenum formatType = VertexFormatType(attribute.format);
@@ -209,11 +225,11 @@
if (VertexFormatIsInt(attribute.format)) {
gl.VertexAttribIPointer(
attribIndex, components, formatType, vertexBuffer.arrayStride,
- reinterpret_cast<void*>(static_cast<intptr_t>(offset + attribute.offset)));
+ reinterpret_cast<void*>(offset + static_cast<intptr_t>(attribute.offset)));
} else {
gl.VertexAttribPointer(
attribIndex, components, formatType, normalized, vertexBuffer.arrayStride,
- reinterpret_cast<void*>(static_cast<intptr_t>(offset + attribute.offset)));
+ reinterpret_cast<void*>(offset + static_cast<intptr_t>(attribute.offset)));
}
}
}
@@ -229,6 +245,8 @@
PerVertexBuffer<Buffer*> mVertexBuffers;
PerVertexBuffer<uint64_t> mVertexBufferOffsets;
+ int32_t mBaseVertex = 0;
+ uint32_t mFirstInstance = 0;
raw_ptr<RenderPipelineBase> mLastPipeline = nullptr;
};
@@ -1113,7 +1131,7 @@
switch (type) {
case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>();
- vertexStateBufferBindingTracker.Apply(gl);
+ vertexStateBufferBindingTracker.Apply(gl, 0, draw->firstInstance);
bindGroupTracker.Apply(gl);
if (lastPipeline->UsesInstanceIndex()) {
@@ -1127,7 +1145,7 @@
case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
- vertexStateBufferBindingTracker.Apply(gl);
+ vertexStateBufferBindingTracker.Apply(gl, draw->baseVertex, draw->firstInstance);
bindGroupTracker.Apply(gl);
const auto topology = lastPipeline->GetGLPrimitiveTopology();
@@ -1137,39 +1155,19 @@
gl.Disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
+ if (lastPipeline->UsesVertexIndex()) {
+ gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstVertex,
+ draw->baseVertex);
+ }
if (lastPipeline->UsesInstanceIndex()) {
gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance,
draw->firstInstance);
}
- if (gl.DrawElementsInstancedBaseVertexBaseInstanceANGLE) {
- gl.DrawElementsInstancedBaseVertexBaseInstanceANGLE(
- topology, draw->indexCount, indexBufferFormat,
- reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
- indexBufferBaseOffset),
- draw->instanceCount, draw->baseVertex, draw->firstInstance);
- } else if (draw->firstInstance > 0) {
- gl.DrawElementsInstancedBaseVertexBaseInstance(
- topology, draw->indexCount, indexBufferFormat,
- reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
- indexBufferBaseOffset),
- draw->instanceCount, draw->baseVertex, draw->firstInstance);
- } else {
- // This branch is only needed on OpenGL < 4.2; ES < 3.2
- if (draw->baseVertex != 0) {
- gl.DrawElementsInstancedBaseVertex(
- topology, draw->indexCount, indexBufferFormat,
- reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
- indexBufferBaseOffset),
- draw->instanceCount, draw->baseVertex);
- } else {
- // This branch is only needed on OpenGL < 3.2; ES < 3.2
- gl.DrawElementsInstanced(
- topology, draw->indexCount, indexBufferFormat,
- reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
- indexBufferBaseOffset),
- draw->instanceCount);
- }
- }
+ gl.DrawElementsInstanced(
+ topology, draw->indexCount, indexBufferFormat,
+ reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
+ indexBufferBaseOffset),
+ draw->instanceCount);
break;
}
@@ -1178,7 +1176,7 @@
if (lastPipeline->UsesInstanceIndex()) {
gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance, 0);
}
- vertexStateBufferBindingTracker.Apply(gl);
+ vertexStateBufferBindingTracker.Apply(gl, 0, 0);
bindGroupTracker.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset;
@@ -1198,7 +1196,7 @@
if (lastPipeline->UsesInstanceIndex()) {
gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance, 0);
}
- vertexStateBufferBindingTracker.Apply(gl);
+ vertexStateBufferBindingTracker.Apply(gl, 0, 0);
bindGroupTracker.Apply(gl);
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
diff --git a/src/dawn/native/opengl/ComputePipelineGL.cpp b/src/dawn/native/opengl/ComputePipelineGL.cpp
index 3344cd5..f193bea 100644
--- a/src/dawn/native/opengl/ComputePipelineGL.cpp
+++ b/src/dawn/native/opengl/ComputePipelineGL.cpp
@@ -47,7 +47,8 @@
MaybeError ComputePipeline::InitializeImpl() {
DAWN_TRY(InitializeBase(ToBackend(GetDevice())->GetGL(), ToBackend(GetLayout()), GetAllStages(),
- /* usesInstanceIndex */ false, /* usesFragDepth */ false));
+ /* usesVertexIndex */ false, /* usesInstanceIndex */ false,
+ /* usesFragDepth */ false));
return {};
}
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index 70e6e73..7f89390 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -334,10 +334,6 @@
TogglesState* deviceToggles) const {
const OpenGLFunctions& gl = mFunctions;
- bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);
-
- bool supportsBaseInstance = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(4, 2);
-
// TODO(crbug.com/dawn/582): Use OES_draw_buffers_indexed where available.
bool supportsIndexedDrawBuffers = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 0);
@@ -363,28 +359,7 @@
bool supportsStencilWriteTexture =
gl.GetVersion().IsDesktop() || gl.IsGLExtensionSupported("GL_OES_texture_stencil8");
- // TODO(crbug.com/dawn/343): We can support the extension variants, but need to load the EXT
- // procs without the extension suffix.
- // We'll also need emulation of shader builtins gl_BaseVertex and gl_BaseInstance.
-
- // supportsBaseVertex |=
- // (gl.IsAtLeastGLES(2, 0) &&
- // (gl.IsGLExtensionSupported("OES_draw_elements_base_vertex") ||
- // gl.IsGLExtensionSupported("EXT_draw_elements_base_vertex"))) ||
- // (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_draw_elements_base_vertex"));
-
- // supportsBaseInstance |=
- // (gl.IsAtLeastGLES(3, 1) && gl.IsGLExtensionSupported("EXT_base_instance")) ||
- // (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_base_instance"));
-
- if (gl.IsAtLeastGLES(3, 1) && gl.IsGLExtensionSupported("GL_ANGLE_base_vertex_base_instance")) {
- supportsBaseVertex = true;
- supportsBaseInstance = true;
- }
-
// TODO(crbug.com/dawn/343): Investigate emulation.
- deviceToggles->Default(Toggle::DisableBaseVertex, !supportsBaseVertex);
- deviceToggles->Default(Toggle::DisableBaseInstance, !supportsBaseInstance);
deviceToggles->Default(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
deviceToggles->Default(Toggle::DisableDepthRead, !supportsDepthRead);
deviceToggles->Default(Toggle::DisableStencilRead, !supportsStencilRead);
diff --git a/src/dawn/native/opengl/PipelineGL.cpp b/src/dawn/native/opengl/PipelineGL.cpp
index 2ca43fe..4025342 100644
--- a/src/dawn/native/opengl/PipelineGL.cpp
+++ b/src/dawn/native/opengl/PipelineGL.cpp
@@ -53,6 +53,7 @@
MaybeError PipelineGL::InitializeBase(const OpenGLFunctions& gl,
const PipelineLayout* layout,
const PerStage<ProgrammableStage>& stages,
+ bool usesVertexIndex,
bool usesInstanceIndex,
bool usesFragDepth) {
mProgram = gl.CreateProgram();
@@ -72,11 +73,11 @@
for (SingleShaderStage stage : IterateStages(activeStages)) {
const ShaderModule* module = ToBackend(stages[stage].module.Get());
GLuint shader;
- DAWN_TRY_ASSIGN(shader, module->CompileShader(gl, stages[stage], stage, usesInstanceIndex,
- usesFragDepth, &combinedSamplers[stage],
- layout, &needsPlaceholderSampler,
- &mNeedsTextureBuiltinUniformBuffer,
- &mBindingPointEmulatedBuiltins));
+ DAWN_TRY_ASSIGN(
+ shader, module->CompileShader(
+ gl, stages[stage], stage, usesVertexIndex, usesInstanceIndex, usesFragDepth,
+ &combinedSamplers[stage], layout, &needsPlaceholderSampler,
+ &mNeedsTextureBuiltinUniformBuffer, &mBindingPointEmulatedBuiltins));
gl.AttachShader(mProgram, shader);
glShaders.push_back(shader);
}
diff --git a/src/dawn/native/opengl/PipelineGL.h b/src/dawn/native/opengl/PipelineGL.h
index 2370f55..3b5ac9e 100644
--- a/src/dawn/native/opengl/PipelineGL.h
+++ b/src/dawn/native/opengl/PipelineGL.h
@@ -74,6 +74,7 @@
MaybeError InitializeBase(const OpenGLFunctions& gl,
const PipelineLayout* layout,
const PerStage<ProgrammableStage>& stages,
+ bool usesVertexIndex,
bool usesInstanceIndex,
bool usesFragDepth);
void DeleteProgram(const OpenGLFunctions& gl);
diff --git a/src/dawn/native/opengl/PipelineLayoutGL.h b/src/dawn/native/opengl/PipelineLayoutGL.h
index bc0fe3a..b12b756 100644
--- a/src/dawn/native/opengl/PipelineLayoutGL.h
+++ b/src/dawn/native/opengl/PipelineLayoutGL.h
@@ -56,9 +56,10 @@
GLuint GetInternalUniformBinding() const;
enum PushConstantLocation {
- FirstInstance = 0,
- MinDepth = 1,
- MaxDepth = 2,
+ FirstVertex = 0,
+ FirstInstance = 1,
+ MinDepth = 2,
+ MaxDepth = 3,
};
private:
diff --git a/src/dawn/native/opengl/RenderPipelineGL.cpp b/src/dawn/native/opengl/RenderPipelineGL.cpp
index a4c2b08..57991a0 100644
--- a/src/dawn/native/opengl/RenderPipelineGL.cpp
+++ b/src/dawn/native/opengl/RenderPipelineGL.cpp
@@ -217,7 +217,7 @@
MaybeError RenderPipeline::InitializeImpl() {
DAWN_TRY(InitializeBase(ToBackend(GetDevice())->GetGL(), ToBackend(GetLayout()), GetAllStages(),
- UsesInstanceIndex(), UsesFragDepth()));
+ UsesVertexIndex(), UsesInstanceIndex(), UsesFragDepth()));
CreateVAOForVertexState();
return {};
}
diff --git a/src/dawn/native/opengl/ShaderModuleGL.cpp b/src/dawn/native/opengl/ShaderModuleGL.cpp
index b2d3aef..8d9e026 100644
--- a/src/dawn/native/opengl/ShaderModuleGL.cpp
+++ b/src/dawn/native/opengl/ShaderModuleGL.cpp
@@ -168,6 +168,7 @@
const OpenGLFunctions& gl,
const ProgrammableStage& programmableStage,
SingleShaderStage stage,
+ bool usesVertexIndex,
bool usesInstanceIndex,
bool usesFragDepth,
CombinedSamplerInfo* combinedSamplers,
@@ -291,6 +292,10 @@
req.tintOptions.disable_robustness = false;
+ if (usesVertexIndex) {
+ req.tintOptions.first_vertex_offset = 4 * PipelineLayout::PushConstantLocation::FirstVertex;
+ }
+
if (usesInstanceIndex) {
req.tintOptions.first_instance_offset =
4 * PipelineLayout::PushConstantLocation::FirstInstance;
diff --git a/src/dawn/native/opengl/ShaderModuleGL.h b/src/dawn/native/opengl/ShaderModuleGL.h
index 71251e4..2c04be3 100644
--- a/src/dawn/native/opengl/ShaderModuleGL.h
+++ b/src/dawn/native/opengl/ShaderModuleGL.h
@@ -89,6 +89,7 @@
ResultOrError<GLuint> CompileShader(const OpenGLFunctions& gl,
const ProgrammableStage& programmableStage,
SingleShaderStage stage,
+ bool usesVertexIndex,
bool usesInstanceIndex,
bool usesFragDepth,
CombinedSamplerInfo* combinedSamplers,
diff --git a/src/dawn/native/opengl/supported_extensions.json b/src/dawn/native/opengl/supported_extensions.json
index 75beb21..b74ba3b 100644
--- a/src/dawn/native/opengl/supported_extensions.json
+++ b/src/dawn/native/opengl/supported_extensions.json
@@ -35,9 +35,5 @@
"GL_OES_EGL_image",
"GL_EXT_texture_format_BGRA8888",
"GL_APPLE_texture_format_BGRA8888"
- ],
-
- "supported_angle_extensions": [
- "GL_ANGLE_base_vertex_base_instance"
]
}
diff --git a/src/dawn/tests/end2end/DrawIndexedTests.cpp b/src/dawn/tests/end2end/DrawIndexedTests.cpp
index b7e5f6c..4d7597a 100644
--- a/src/dawn/tests/end2end/DrawIndexedTests.cpp
+++ b/src/dawn/tests/end2end/DrawIndexedTests.cpp
@@ -163,6 +163,21 @@
Test(3, 1, 0, 4, 0, 0, notFilled, filled);
// Test a draw with only the last 3 indices of the second quad (bottom left triangle)
Test(3, 1, 3, 4, 0, 0, filled, notFilled);
+}
+
+// Test the parameter 'baseVertex' of DrawIndexed() works.
+TEST_P(DrawIndexedTest, NegativeBaseVertex) {
+ DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_base_vertex"));
+
+ // TODO(crbug.com/343178421): ANGLE/SwiftShader and ANGLE/D3D11 fail with negative baseVertex.
+ DAWN_SUPPRESS_TEST_IF(IsANGLESwiftShader());
+ DAWN_SUPPRESS_TEST_IF(IsANGLED3D11());
+
+ // Also failing on Qualcomm GLES.
+ DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());
+
+ utils::RGBA8 filled(0, 255, 0, 255);
+ utils::RGBA8 notFilled(0, 0, 0, 0);
// Test negative baseVertex
// Test a draw with only the first 3 indices of the first quad (bottom left triangle)
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 1cbcee4..ce607a0 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -257,7 +257,8 @@
data.Add<ast::transform::CanonicalizeEntryPointIO::Config>(
ast::transform::CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
- data.Add<ast::transform::OffsetFirstIndex::Config>(std::nullopt, options.first_instance_offset);
+ data.Add<ast::transform::OffsetFirstIndex::Config>(options.first_vertex_offset,
+ options.first_instance_offset);
data.Add<ast::transform::ClampFragDepth::Config>(options.depth_range_offsets);
diff --git a/src/tint/lang/glsl/writer/common/options.h b/src/tint/lang/glsl/writer/common/options.h
index f6f114a..3ba7540 100644
--- a/src/tint/lang/glsl/writer/common/options.h
+++ b/src/tint/lang/glsl/writer/common/options.h
@@ -156,6 +156,9 @@
/// Options used in the binding mappings for external textures
ExternalTextureOptions external_texture_options = {};
+ /// Offset of the firstVertex push constant.
+ std::optional<int32_t> first_vertex_offset;
+
/// Offset of the firstInstance push constant.
std::optional<int32_t> first_instance_offset;
@@ -176,6 +179,7 @@
combined_samplers_info,
binding_remapper_options,
external_texture_options,
+ first_vertex_offset,
first_instance_offset,
depth_range_offsets,
texture_builtins_from_uniform);