Add Toggles to disable base vertex and base instance rendering

These are not supported on some older OpenGL, OpenGL ES, and iOS
devices.

Bug: dawn:343
Change-Id: I70def749ae57fcfe2895f8556674dd241941d3d3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16163
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Austin Eng 2020-02-26 08:24:20 +00:00 committed by Commit Bot service account
parent 2f0f850da8
commit a9d7d47842
11 changed files with 120 additions and 26 deletions

View File

@ -27,13 +27,17 @@
namespace dawn_native { namespace dawn_native {
RenderEncoderBase::RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext) RenderEncoderBase::RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext)
: ProgrammablePassEncoder(device, encodingContext) { : ProgrammablePassEncoder(device, encodingContext),
mDisableBaseVertex(device->IsToggleEnabled(Toggle::DisableBaseVertex)),
mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {
} }
RenderEncoderBase::RenderEncoderBase(DeviceBase* device, RenderEncoderBase::RenderEncoderBase(DeviceBase* device,
EncodingContext* encodingContext, EncodingContext* encodingContext,
ErrorTag errorTag) ErrorTag errorTag)
: ProgrammablePassEncoder(device, encodingContext, errorTag) { : ProgrammablePassEncoder(device, encodingContext, errorTag),
mDisableBaseVertex(device->IsToggleEnabled(Toggle::DisableBaseVertex)),
mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {
} }
void RenderEncoderBase::Draw(uint32_t vertexCount, void RenderEncoderBase::Draw(uint32_t vertexCount,
@ -41,6 +45,10 @@ namespace dawn_native {
uint32_t firstVertex, uint32_t firstVertex,
uint32_t firstInstance) { uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (mDisableBaseInstance && firstInstance != 0) {
return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
}
DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw); DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw);
draw->vertexCount = vertexCount; draw->vertexCount = vertexCount;
draw->instanceCount = instanceCount; draw->instanceCount = instanceCount;
@ -57,6 +65,13 @@ namespace dawn_native {
int32_t baseVertex, int32_t baseVertex,
uint32_t firstInstance) { uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (mDisableBaseInstance && firstInstance != 0) {
return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
}
if (mDisableBaseInstance && baseVertex != 0) {
return DAWN_VALIDATION_ERROR("Non-zero base vertex not supported");
}
DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed); DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed);
draw->indexCount = indexCount; draw->indexCount = indexCount;
draw->instanceCount = instanceCount; draw->instanceCount = instanceCount;

View File

@ -45,6 +45,10 @@ namespace dawn_native {
protected: protected:
// Construct an "error" render encoder base. // Construct an "error" render encoder base.
RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext, ErrorTag errorTag); RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext, ErrorTag errorTag);
private:
const bool mDisableBaseVertex;
const bool mDisableBaseInstance;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -106,6 +106,13 @@ namespace dawn_native {
{"metal_disable_sampler_compare", {"metal_disable_sampler_compare",
"Disables the use of sampler compare on Metal. This is unsupported before A9 " "Disables the use of sampler compare on Metal. This is unsupported before A9 "
"processors."}}, "processors."}},
{Toggle::DisableBaseVertex,
{"disable_base_vertex",
"Disables the use of non-zero base vertex which is unsupported on some platforms."}},
{Toggle::DisableBaseInstance,
{"disable_base_instance",
"Disables the use of non-zero base instance which is unsupported on some "
"platforms."}},
}}; }};
} // anonymous namespace } // anonymous namespace

View File

@ -37,6 +37,8 @@ namespace dawn_native {
UseSpvcParser, UseSpvcParser,
VulkanUseD32S8, VulkanUseD32S8,
MetalDisableSamplerCompare, MetalDisableSamplerCompare,
DisableBaseVertex,
DisableBaseInstance,
EnumCount, EnumCount,
InvalidEnum = EnumCount, InvalidEnum = EnumCount,

View File

@ -1018,11 +1018,19 @@ namespace dawn_native { namespace metal {
// The instance count must be non-zero, otherwise no-op // The instance count must be non-zero, otherwise no-op
if (draw->instanceCount != 0) { if (draw->instanceCount != 0) {
[encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology() // MTLFeatureSet_iOS_GPUFamily3_v1 does not support baseInstance
vertexStart:draw->firstVertex if (draw->firstInstance == 0) {
vertexCount:draw->vertexCount [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology()
instanceCount:draw->instanceCount vertexStart:draw->firstVertex
baseInstance:draw->firstInstance]; vertexCount:draw->vertexCount
instanceCount:draw->instanceCount];
} else {
[encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology()
vertexStart:draw->firstVertex
vertexCount:draw->vertexCount
instanceCount:draw->instanceCount
baseInstance:draw->firstInstance];
}
} }
} break; } break;
@ -1037,15 +1045,27 @@ namespace dawn_native { namespace metal {
// The index and instance count must be non-zero, otherwise no-op // The index and instance count must be non-zero, otherwise no-op
if (draw->indexCount != 0 && draw->instanceCount != 0) { if (draw->indexCount != 0 && draw->instanceCount != 0) {
[encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology() // MTLFeatureSet_iOS_GPUFamily3_v1 does not support baseInstance and
indexCount:draw->indexCount // baseVertex.
indexType:lastPipeline->GetMTLIndexType() if (draw->baseVertex == 0 && draw->firstInstance == 0) {
indexBuffer:indexBuffer [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
indexBufferOffset:indexBufferBaseOffset + indexCount:draw->indexCount
draw->firstIndex * formatSize indexType:lastPipeline->GetMTLIndexType()
instanceCount:draw->instanceCount indexBuffer:indexBuffer
baseVertex:draw->baseVertex indexBufferOffset:indexBufferBaseOffset +
baseInstance:draw->firstInstance]; draw->firstIndex * formatSize
instanceCount:draw->instanceCount];
} else {
[encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
indexCount:draw->indexCount
indexType:lastPipeline->GetMTLIndexType()
indexBuffer:indexBuffer
indexBufferOffset:indexBufferBaseOffset +
draw->firstIndex * formatSize
instanceCount:draw->instanceCount
baseVertex:draw->baseVertex
baseInstance:draw->firstInstance];
}
} }
} break; } break;

View File

@ -76,6 +76,15 @@ namespace dawn_native { namespace metal {
#endif #endif
// TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive. // TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive.
SetToggle(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare); SetToggle(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare);
bool haveBaseVertexBaseInstance = true;
#if defined(DAWN_PLATFORM_IOS)
haveBaseVertexBaseInstance =
[mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
#endif
// TODO(crbug.com/dawn/343): Investigate emulation.
SetToggle(Toggle::DisableBaseVertex, !haveBaseVertexBaseInstance);
SetToggle(Toggle::DisableBaseInstance, !haveBaseVertexBaseInstance);
} }
// TODO(jiawei.shao@intel.com): tighten this workaround when the driver bug is fixed. // TODO(jiawei.shao@intel.com): tighten this workaround when the driver bug is fixed.

View File

@ -869,12 +869,23 @@ namespace dawn_native { namespace opengl {
indexBufferBaseOffset), indexBufferBaseOffset),
draw->instanceCount, draw->baseVertex, draw->firstInstance); draw->instanceCount, draw->baseVertex, draw->firstInstance);
} else { } else {
// This branch is only needed on OpenGL < 4.2 // This branch is only needed on OpenGL < 4.2; ES < 3.2
gl.DrawElementsInstancedBaseVertex( if (draw->baseVertex != 0) {
lastPipeline->GetGLPrimitiveTopology(), draw->indexCount, formatType, gl.DrawElementsInstancedBaseVertex(
reinterpret_cast<void*>(draw->firstIndex * formatSize + lastPipeline->GetGLPrimitiveTopology(), draw->indexCount,
indexBufferBaseOffset), formatType,
draw->instanceCount, draw->baseVertex); reinterpret_cast<void*>(draw->firstIndex * formatSize +
indexBufferBaseOffset),
draw->instanceCount, draw->baseVertex);
} else {
// This branch is only needed on OpenGL < 3.2; ES < 3.2
gl.DrawElementsInstanced(
lastPipeline->GetGLPrimitiveTopology(), draw->indexCount,
formatType,
reinterpret_cast<void*>(draw->firstIndex * formatSize +
indexBufferBaseOffset),
draw->instanceCount);
}
} }
} break; } break;

View File

@ -36,6 +36,7 @@ namespace dawn_native { namespace opengl {
const DeviceDescriptor* descriptor, const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions) const OpenGLFunctions& functions)
: DeviceBase(adapter, descriptor), gl(functions) { : DeviceBase(adapter, descriptor), gl(functions) {
InitTogglesFromDriver();
if (descriptor != nullptr) { if (descriptor != nullptr) {
ApplyToggleOverrides(descriptor); ApplyToggleOverrides(descriptor);
} }
@ -46,6 +47,30 @@ namespace dawn_native { namespace opengl {
BaseDestructor(); BaseDestructor();
} }
void Device::InitTogglesFromDriver() {
bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);
bool supportsBaseInstance = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(4, 2);
// 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"));
// TODO(crbug.com/dawn/343): Investigate emulation.
SetToggle(Toggle::DisableBaseVertex, !supportsBaseVertex);
SetToggle(Toggle::DisableBaseInstance, !supportsBaseInstance);
}
const GLFormat& Device::GetGLFormat(const Format& format) { const GLFormat& Device::GetGLFormat(const Format& format) {
ASSERT(format.isSupported); ASSERT(format.isSupported);
ASSERT(format.GetIndex() < mFormatTable.size()); ASSERT(format.GetIndex() < mFormatTable.size());

View File

@ -89,6 +89,7 @@ namespace dawn_native { namespace opengl {
TextureBase* texture, TextureBase* texture,
const TextureViewDescriptor* descriptor) override; const TextureViewDescriptor* descriptor) override;
void InitTogglesFromDriver();
void CheckPassedFences(); void CheckPassedFences();
void Destroy() override; void Destroy() override;
MaybeError WaitForIdleForDestruction() override; MaybeError WaitForIdleForDestruction() override;

View File

@ -74,12 +74,12 @@ namespace dawn_native { namespace opengl {
return mSupportedGLExtensionsSet.count(extension) != 0; return mSupportedGLExtensionsSet.count(extension) != 0;
} }
bool OpenGLFunctions::IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) { bool OpenGLFunctions::IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) const {
return mStandard == Standard::Desktop && return mStandard == Standard::Desktop &&
std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion); std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
} }
bool OpenGLFunctions::IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) { bool OpenGLFunctions::IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) const {
return mStandard == Standard::ES && return mStandard == Standard::ES &&
std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion); std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
} }

View File

@ -25,8 +25,8 @@ namespace dawn_native { namespace opengl {
public: public:
MaybeError Initialize(GetProcAddress getProc); MaybeError Initialize(GetProcAddress getProc);
bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion); bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) const;
bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion); bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) const;
bool IsGLExtensionSupported(const char* extension) const; bool IsGLExtensionSupported(const char* extension) const;