Commit 064fc28a authored by Laszlo Agocs's avatar Laszlo Agocs

Add support for selecting the shader variant

For instance the Qt Quick renderer will want the Batchable variant for
a vertex shader when rendering merged batches. Make it possible to
communicate this to the backends.
parent 7cffae0e
......@@ -990,10 +990,16 @@ QRhiGraphicsShaderStage::QRhiGraphicsShaderStage()
/*!
Constructs a shader stage description with the \a type of the stage and the
\a shader.
The shader variant \a v defaults to QBakedShaderKey::StandardShader. A
QBakedShader pack contains multiple source and binary versions of a shader.
In addition, it can also contain variants of the shader with slightly
modified code. \a v can then be used to select the desired variant.
*/
QRhiGraphicsShaderStage::QRhiGraphicsShaderStage(Type type, const QBakedShader &shader)
QRhiGraphicsShaderStage::QRhiGraphicsShaderStage(Type type, const QBakedShader &shader, QBakedShaderKey::ShaderVariant v)
: m_type(type),
m_shader(shader)
m_shader(shader),
m_shaderVariant(v)
{
}
......@@ -1006,7 +1012,8 @@ QRhiGraphicsShaderStage::QRhiGraphicsShaderStage(Type type, const QBakedShader &
bool operator==(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW
{
return a.type() == b.type()
&& a.shader() == b.shader();
&& a.shader() == b.shader()
&& a.shaderVariant() == b.shaderVariant();
}
/*!
......@@ -1027,7 +1034,7 @@ bool operator!=(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage
*/
uint qHash(const QRhiGraphicsShaderStage &v, uint seed) Q_DECL_NOTHROW
{
return v.type() + qHash(v.shader(), seed);
return v.type() + qHash(v.shader(), seed) + v.shaderVariant();
}
/*!
......
......@@ -260,7 +260,8 @@ public:
};
QRhiGraphicsShaderStage();
QRhiGraphicsShaderStage(Type type, const QBakedShader &shader);
QRhiGraphicsShaderStage(Type type, const QBakedShader &shader,
QBakedShaderKey::ShaderVariant v = QBakedShaderKey::StandardShader);
Type type() const { return m_type; }
void setType(Type t) { m_type = t; }
......@@ -268,9 +269,13 @@ public:
QBakedShader shader() const { return m_shader; }
void setShader(const QBakedShader &s) { m_shader = s; }
QBakedShaderKey::ShaderVariant shaderVariant() const { return m_shaderVariant; }
void setShaderVariant(QBakedShaderKey::ShaderVariant v) { m_shaderVariant = v; }
private:
Type m_type;
QBakedShader m_shader;
QBakedShaderKey::ShaderVariant m_shaderVariant = QBakedShaderKey::StandardShader;
Q_DECL_UNUSED_MEMBER quint64 m_reserved;
};
......
......@@ -2647,13 +2647,13 @@ static inline D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
}
}
static QByteArray compileHlslShaderSource(const QBakedShader &shader, QString *error)
static QByteArray compileHlslShaderSource(const QBakedShader &shader, QBakedShaderKey::ShaderVariant shaderVariant, QString *error)
{
QBakedShaderCode dxbc = shader.shader({ QBakedShaderKey::DxbcShader, 50 });
QBakedShaderCode dxbc = shader.shader({ QBakedShaderKey::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
return dxbc.shader();
QBakedShaderCode hlslSource = shader.shader({ QBakedShaderKey::HlslShader, 50 });
QBakedShaderCode hlslSource = shader.shader({ QBakedShaderKey::HlslShader, 50, shaderVariant });
if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray();
......@@ -2782,7 +2782,7 @@ bool QD3D11GraphicsPipeline::build()
QByteArray vsByteCode;
for (const QRhiGraphicsShaderStage &shaderStage : qAsConst(m_shaderStages)) {
QString error;
QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), &error);
QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
......
......@@ -2353,7 +2353,7 @@ bool QGles2GraphicsPipeline::build()
else
ver = { 120 };
const QBakedShader bakedShader = shaderStage.shader();
const QByteArray source = bakedShader.shader({ QBakedShaderKey::GlslShader, ver }).shader();
const QByteArray source = bakedShader.shader({ QBakedShaderKey::GlslShader, ver, shaderStage.shaderVariant() }).shader();
if (source.isEmpty()) {
qWarning() << "No GLSL" << ver.version() << "shader code found in baked shader" << bakedShader;
return false;
......
......@@ -129,7 +129,8 @@ struct QRhiMetalData
MTLRenderPassDescriptor *createDefaultRenderPass(bool hasDepthStencil,
const QRhiColorClearValue &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue);
id<MTLLibrary> createMetalLib(const QBakedShader &shader, QString *error, QByteArray *entryPoint);
id<MTLLibrary> createMetalLib(const QBakedShader &shader, QBakedShaderKey::ShaderVariant shaderVariant,
QString *error, QByteArray *entryPoint);
id<MTLFunction> createMSLShaderFunction(id<MTLLibrary> lib, const QByteArray &entryPoint);
struct DeferredReleaseEntry {
......@@ -2654,9 +2655,10 @@ static inline MTLCullMode toMetalCullMode(QRhiGraphicsPipeline::CullMode c)
}
}
id<MTLLibrary> QRhiMetalData::createMetalLib(const QBakedShader &shader, QString *error, QByteArray *entryPoint)
id<MTLLibrary> QRhiMetalData::createMetalLib(const QBakedShader &shader, QBakedShaderKey::ShaderVariant shaderVariant,
QString *error, QByteArray *entryPoint)
{
QBakedShaderCode mtllib = shader.shader({ QBakedShaderKey::MetalLibShader, 12 });
QBakedShaderCode mtllib = shader.shader({ QBakedShaderKey::MetalLibShader, 12, shaderVariant });
if (!mtllib.shader().isEmpty()) {
dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(),
mtllib.shader().size(),
......@@ -2674,7 +2676,7 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QBakedShader &shader, QString
}
}
QBakedShaderCode mslSource = shader.shader({ QBakedShaderKey::MslShader, 12 });
QBakedShaderCode mslSource = shader.shader({ QBakedShaderKey::MslShader, 12, shaderVariant });
if (mslSource.shader().isEmpty()) {
qWarning() << "No MSL 1.2 code found in baked shader" << shader;
return nil;
......@@ -2756,7 +2758,7 @@ bool QMetalGraphicsPipeline::build()
for (const QRhiGraphicsShaderStage &shaderStage : qAsConst(m_shaderStages)) {
QString error;
QByteArray entryPoint;
id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), &error, &entryPoint);
id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint);
if (!lib) {
qWarning("MSL shader compilation failed: %s", qPrintable(error));
return false;
......
......@@ -4608,7 +4608,7 @@ bool QVkGraphicsPipeline::build()
QVarLengthArray<VkPipelineShaderStageCreateInfo, 4> shaderStageCreateInfos;
for (const QRhiGraphicsShaderStage &shaderStage : m_shaderStages) {
const QBakedShader bakedShader = shaderStage.shader();
const QBakedShaderCode spirv = bakedShader.shader({ QBakedShaderKey::SpirvShader, 100 });
const QBakedShaderCode spirv = bakedShader.shader({ QBakedShaderKey::SpirvShader, 100, shaderStage.shaderVariant() });
if (spirv.shader().isEmpty()) {
qWarning() << "No SPIR-V 1.0 shader code found in baked shader" << bakedShader;
return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment