rhi: Enhance line width and point size support

...but this will vary between backends, or in some cases
even between implementations of the same API.

Point size is settable only via the vertex shader (gl_PointSize).
It is silently ignored with D3D and HLSL.

Line widths other than 1 are supported only on OpenGL and Vulkan.
(but this is in fact deprecated with GL and optional with Vulkan)

Add QRhi::Feature values for both.

The line width is now settable on QRhiGraphicsPipeline. It is not a
dynamic state since the static, per-pipeline width is good enough for
most cases. (and the feature is not supported on half of the backends
anyways so it will get limited use in practice).

Change-Id: I6d3a32269527c452b794b2cb8b0f03101eab40b2
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Laszlo Agocs 2019-06-24 10:22:50 +02:00
parent 56fb2266f2
commit 854ddb0301
9 changed files with 57 additions and 9 deletions

View File

@ -494,7 +494,23 @@ QT_BEGIN_NAMESPACE
extension. When false, only 16-bit unsigned elements are supported in the
index buffer.
\value Compute Indicates that compute shaders are supported.
\value Compute Indicates that compute shaders, image load/store, and
storage buffers are supported.
\value WideLines Indicates that lines with a width other than 1 are
supported. When reported as not supported, the line width set on the
graphics pipeline state is ignored. This can always be false with some
backends (D3D11, Metal). With Vulkan, the value depends on the
implementation.
\value VertexShaderPointSize Indicates that the size of rasterized points
set via \c{gl_PointSize} in the vertex shader is taken into account. When
reported as not supported, drawing points with a size other than 1 is not
supported. Setting \c{gl_PointSize} in the shader is still valid then, but
is ignored. (for example, when generating HLSL, the assignment is silently
dropped from the generated code) Note that some APIs (Metal, Vulkan)
require the point size to be set in the shader explicitly whenever drawing
points, even when the size is 1, as they do not automatically default to 1.
*/
/*!

View File

@ -1068,6 +1068,9 @@ public:
int sampleCount() const { return m_sampleCount; }
void setSampleCount(int s) { m_sampleCount = s; }
float lineWidth() const { return m_lineWidth; }
void setLineWidth(float width) { m_lineWidth = width; }
QVector<QRhiShaderStage> shaderStages() const { return m_shaderStages; }
void setShaderStages(const QVector<QRhiShaderStage> &stages) { m_shaderStages = stages; }
@ -1098,6 +1101,7 @@ protected:
quint32 m_stencilReadMask = 0xFF;
quint32 m_stencilWriteMask = 0xFF;
int m_sampleCount = 1;
float m_lineWidth = 1.0f;
QVector<QRhiShaderStage> m_shaderStages;
QRhiVertexInputLayout m_vertexInputLayout;
QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
@ -1312,7 +1316,9 @@ public:
NPOTTextureRepeat,
RedOrAlpha8IsRed,
ElementIndexUint,
Compute
Compute,
WideLines,
VertexShaderPointSize
};
enum BeginFrameFlag {

View File

@ -378,6 +378,10 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::Compute:
return true;
case QRhi::WideLines:
return false;
case QRhi::VertexShaderPointSize:
return false;
default:
Q_UNREACHABLE();
return false;

View File

@ -618,6 +618,10 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return caps.elementIndexUint;
case QRhi::Compute:
return false;
case QRhi::WideLines:
return true;
case QRhi::VertexShaderPointSize:
return true;
default:
Q_UNREACHABLE();
return false;
@ -1849,6 +1853,9 @@ void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps)
f->glDisable(GL_STENCIL_TEST);
}
if (psD->topology() == QRhiGraphicsPipeline::Lines || psD->topology() == QRhiGraphicsPipeline::LineStrip)
f->glLineWidth(psD->m_lineWidth);
f->glUseProgram(psD->program);
}

View File

@ -523,6 +523,10 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::Compute:
return true;
case QRhi::WideLines:
return false;
case QRhi::VertexShaderPointSize:
return true;
default:
Q_UNREACHABLE();
return false;

View File

@ -489,6 +489,9 @@ bool QRhiVulkan::create(QRhi::Flags flags)
// elsewhere states that the minimum bufferOffset is 4...
texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
f->vkGetPhysicalDeviceFeatures(physDev, &physDevFeatures);
hasWideLines = physDevFeatures.wideLines;
if (!importedAllocator) {
VmaVulkanFunctions afuncs;
afuncs.vkGetPhysicalDeviceProperties = wrap_vkGetPhysicalDeviceProperties;
@ -3489,24 +3492,21 @@ QMatrix4x4 QRhiVulkan::clipSpaceCorrMatrix() const
bool QRhiVulkan::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
{
VkPhysicalDeviceFeatures features;
f->vkGetPhysicalDeviceFeatures(physDev, &features);
// Note that with some SDKs the validation layer gives an odd warning about
// BC not being supported, even when our check here succeeds. Not much we
// can do about that.
if (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7) {
if (!features.textureCompressionBC)
if (!physDevFeatures.textureCompressionBC)
return false;
}
if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8) {
if (!features.textureCompressionETC2)
if (!physDevFeatures.textureCompressionETC2)
return false;
}
if (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12) {
if (!features.textureCompressionASTC_LDR)
if (!physDevFeatures.textureCompressionASTC_LDR)
return false;
}
@ -3545,6 +3545,10 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::Compute:
return hasCompute;
case QRhi::WideLines:
return hasWideLines;
case QRhi::VertexShaderPointSize:
return true;
default:
Q_UNREACHABLE();
return false;
@ -5612,7 +5616,7 @@ bool QVkGraphicsPipeline::build()
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
rastInfo.lineWidth = 1.0f;
rastInfo.lineWidth = rhiD->hasWideLines ? m_lineWidth : 1.0f;
pipelineInfo.pRasterizationState = &rastInfo;
VkPipelineMultisampleStateCreateInfo msInfo;

View File

@ -783,9 +783,11 @@ public:
QVkAllocator allocator = nullptr;
QVulkanFunctions *f = nullptr;
QVulkanDeviceFunctions *df = nullptr;
VkPhysicalDeviceFeatures physDevFeatures;
VkPhysicalDeviceProperties physDevProperties;
VkDeviceSize ubufAlign;
VkDeviceSize texbufAlign;
bool hasWideLines = false;
bool debugMarkersAvailable = false;
bool vertexAttribDivisorAvailable = false;

View File

@ -91,6 +91,9 @@ void Window::customInit()
if (!m_r->isFeatureSupported(QRhi::Compute))
qFatal("Compute is not supported");
if (!m_r->isFeatureSupported(QRhi::VertexShaderPointSize))
qWarning("Point sizes other than 1 not supported");
// compute pass
d.sbuf = m_r->newBuffer(QRhiBuffer::Immutable,

View File

@ -172,6 +172,8 @@ void Window::customInit()
qDebug("isFeatureSupported(RedOrAlpha8IsRed): %d", m_r->isFeatureSupported(QRhi::RedOrAlpha8IsRed));
qDebug("isFeatureSupported(ElementIndexUint): %d", m_r->isFeatureSupported(QRhi::ElementIndexUint));
qDebug("isFeatureSupported(Compute): %d", m_r->isFeatureSupported(QRhi::Compute));
qDebug("isFeatureSupported(WideLines): %d", m_r->isFeatureSupported(QRhi::WideLines));
qDebug("isFeatureSupported(VertexShaderPointSize): %d", m_r->isFeatureSupported(QRhi::VertexShaderPointSize));
qDebug("Min 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMin));
qDebug("Max 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMax));
qDebug("Max color attachment count: %d", m_r->resourceLimit(QRhi::MaxColorAttachments));