Commit ff38106d by Charlie Lao Committed by Commit Bot

Vulkan: Use specialization constant for halfRenderAreaWidth

halfRenderArea is used by fragment shader to adjust gl_FragCoord for rotation and yflip compensation. This CL bakes halfRenderAreaWidth into shader via specialization constant, thus allow compiler to consolidate the calculation into one MAD instruction. Bug: b/173800146 Change-Id: Id66301278e3389e2582369b695825e632bccecee Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2551541 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 3f564fc7
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 245 #define ANGLE_SH_VERSION 246
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -813,8 +813,10 @@ enum class SpecializationConstantId : uint32_t ...@@ -813,8 +813,10 @@ enum class SpecializationConstantId : uint32_t
{ {
LineRasterEmulation = 0, LineRasterEmulation = 0,
SurfaceRotation = 1, SurfaceRotation = 1,
DrawableWidth = 2,
DrawableHeight = 3,
InvalidEnum = 2, InvalidEnum = 4,
EnumCount = InvalidEnum, EnumCount = InvalidEnum,
}; };
...@@ -838,8 +840,9 @@ enum class SpecConstUsage : uint32_t ...@@ -838,8 +840,9 @@ enum class SpecConstUsage : uint32_t
LineRasterEmulation = 0, LineRasterEmulation = 0,
YFlip = 1, YFlip = 1,
Rotation = 2, Rotation = 2,
DrawableSize = 3,
InvalidEnum = 3, InvalidEnum = 4,
EnumCount = InvalidEnum, EnumCount = InvalidEnum,
}; };
......
...@@ -467,7 +467,13 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler, ...@@ -467,7 +467,13 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
{ {
flipXY = driverUniforms->getFlipXYRef(); flipXY = driverUniforms->getFlipXYRef();
} }
TIntermBinary *pivot = driverUniforms->getHalfRenderAreaRef();
TIntermBinary *pivot = rotationSpecConst->getHalfRenderArea();
if (!pivot)
{
pivot = driverUniforms->getHalfRenderAreaRef();
}
TIntermTyped *fragRotation = nullptr; TIntermTyped *fragRotation = nullptr;
if (compileOptions & SH_ADD_PRE_ROTATION) if (compileOptions & SH_ADD_PRE_ROTATION)
{ {
......
...@@ -22,6 +22,8 @@ namespace ...@@ -22,6 +22,8 @@ namespace
{ {
constexpr ImmutableString kSurfaceRotationSpecConstVarName = constexpr ImmutableString kSurfaceRotationSpecConstVarName =
ImmutableString("ANGLESurfaceRotation"); ImmutableString("ANGLESurfaceRotation");
constexpr ImmutableString kDrawableWidthSpecConstVarName = ImmutableString("ANGLEDrawableWidth");
constexpr ImmutableString kDrawableHeightSpecConstVarName = ImmutableString("ANGLEDrawableHeight");
// When an Android surface is rotated differently than the device's native orientation, ANGLE must // When an Android surface is rotated differently than the device's native orientation, ANGLE must
// rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader. The following // rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader. The following
...@@ -52,6 +54,19 @@ constexpr Mat2x2EnumMap kFragRotationMatrices = { ...@@ -52,6 +54,19 @@ constexpr Mat2x2EnumMap kFragRotationMatrices = {
{vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}}, {vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}}}}; {vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}}}};
// TODO: https://issuetracker.google.com/174066134. This is to make sure the specialization constant
// code path behaves exactly the same as driver uniform code path. Not sure why this has to be
// different from kFragRotationMatrices.
constexpr Mat2x2EnumMap kHalfRenderAreaRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}}}};
// Returns mat2(m0, m1, m2, m3) // Returns mat2(m0, m1, m2, m3)
TIntermAggregate *CreateMat2x2(const Mat2x2EnumMap &matrix, vk::SurfaceRotation rotation) TIntermAggregate *CreateMat2x2(const Mat2x2EnumMap &matrix, vk::SurfaceRotation rotation)
{ {
...@@ -220,7 +235,7 @@ TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap ...@@ -220,7 +235,7 @@ TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap
} }
} // anonymous namespace } // anonymous namespace
FlipRotateSpecConst::FlipRotateSpecConst() : mSpecConstSymbol(nullptr) {} FlipRotateSpecConst::FlipRotateSpecConst() : mSymbolTable(nullptr), mSpecConstSymbol(nullptr) {}
FlipRotateSpecConst::~FlipRotateSpecConst() FlipRotateSpecConst::~FlipRotateSpecConst()
{ {
...@@ -236,17 +251,29 @@ void FlipRotateSpecConst::generateSymbol(TSymbolTable *symbolTable) ...@@ -236,17 +251,29 @@ void FlipRotateSpecConst::generateSymbol(TSymbolTable *symbolTable)
new TVariable(symbolTable, kSurfaceRotationSpecConstVarName, new TVariable(symbolTable, kSurfaceRotationSpecConstVarName,
StaticType::GetBasic<EbtUInt>(), SymbolType::AngleInternal); StaticType::GetBasic<EbtUInt>(), SymbolType::AngleInternal);
mSpecConstSymbol = new TIntermSymbol(specConstVar); mSpecConstSymbol = new TIntermSymbol(specConstVar);
mSymbolTable = symbolTable;
} }
void FlipRotateSpecConst::outputLayoutString(TInfoSinkBase &sink) const void FlipRotateSpecConst::outputLayoutString(TInfoSinkBase &sink) const
{ {
// Only emit specialized const layout string if it has been referenced. // Only emit specialized const layout string if it has been referenced.
if (mUsageBits.any()) if (mUsageBits.test(vk::SpecConstUsage::YFlip) || mUsageBits.test(vk::SpecConstUsage::Rotation))
{ {
sink << "layout(constant_id=" sink << "layout(constant_id="
<< static_cast<uint32_t>(vk::SpecializationConstantId::SurfaceRotation) << static_cast<uint32_t>(vk::SpecializationConstantId::SurfaceRotation)
<< ") const uint " << kSurfaceRotationSpecConstVarName << " = 0;\n\n"; << ") const uint " << kSurfaceRotationSpecConstVarName << " = 0;\n\n";
} }
if (mUsageBits.test(vk::SpecConstUsage::DrawableSize))
{
sink << "layout(constant_id="
<< static_cast<uint32_t>(vk::SpecializationConstantId::DrawableWidth)
<< ") const uint " << kDrawableWidthSpecConstVarName << " = 0;\n\n";
sink << "layout(constant_id="
<< static_cast<uint32_t>(vk::SpecializationConstantId::DrawableHeight)
<< ") const uint " << kDrawableHeightSpecConstVarName << " = 0;\n\n";
}
} }
TIntermTyped *FlipRotateSpecConst::getMultiplierXForDFdx() TIntermTyped *FlipRotateSpecConst::getMultiplierXForDFdx()
...@@ -313,6 +340,16 @@ TIntermTyped *FlipRotateSpecConst::getFragRotationMatrix() ...@@ -313,6 +340,16 @@ TIntermTyped *FlipRotateSpecConst::getFragRotationMatrix()
return GenerateMat2x2ArrayWithIndex(kFragRotationMatrices, mSpecConstSymbol); return GenerateMat2x2ArrayWithIndex(kFragRotationMatrices, mSpecConstSymbol);
} }
TIntermTyped *FlipRotateSpecConst::getHalfRenderAreaRotationMatrix()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::Rotation);
return GenerateMat2x2ArrayWithIndex(kHalfRenderAreaRotationMatrices, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getFlipXY() TIntermTyped *FlipRotateSpecConst::getFlipXY()
{ {
if (!mSpecConstSymbol) if (!mSpecConstSymbol)
...@@ -383,4 +420,49 @@ TIntermTyped *FlipRotateSpecConst::getFragRotationMultiplyFlipXY() ...@@ -383,4 +420,49 @@ TIntermTyped *FlipRotateSpecConst::getFragRotationMultiplyFlipXY()
return CreateVec2ArrayWithIndex(kFragRotationMultiplyFlipXY, 1.0, mSpecConstSymbol); return CreateVec2ArrayWithIndex(kFragRotationMultiplyFlipXY, 1.0, mSpecConstSymbol);
} }
TIntermSymbol *FlipRotateSpecConst::getDrawableWidth()
{
TVariable *widthSpecConstVar =
new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName,
StaticType::GetBasic<EbtFloat>(), SymbolType::AngleInternal);
TIntermSymbol *drawableWidth = new TIntermSymbol(widthSpecConstVar);
return drawableWidth;
}
TIntermSymbol *FlipRotateSpecConst::getDrawableHeight()
{
TVariable *heightSpecConstVar =
new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName,
StaticType::GetBasic<EbtFloat>(), SymbolType::AngleInternal);
TIntermSymbol *drawableHeight = new TIntermSymbol(heightSpecConstVar);
return drawableHeight;
}
TIntermBinary *FlipRotateSpecConst::getHalfRenderArea()
{
if (!mSymbolTable)
{
return nullptr;
}
// vec2 drawableSize(drawableWidth, drawableHeight)
auto vec2Type = new TType(EbtFloat, 2);
TIntermSequence *widthHeightArgs = new TIntermSequence();
widthHeightArgs->push_back(getDrawableWidth());
widthHeightArgs->push_back(getDrawableHeight());
TIntermAggregate *drawableSize =
TIntermAggregate::CreateConstructor(*vec2Type, widthHeightArgs);
// drawableSize * 0.5f
TIntermBinary *halfRenderArea =
new TIntermBinary(EOpVectorTimesScalar, drawableSize, CreateFloatNode(0.5));
mUsageBits.set(vk::SpecConstUsage::DrawableSize);
// drawableSize * 0.5f * halfRenderAreaRotationMatrix (See comment in
// kHalfRenderAreaRotationMatrices)
TIntermBinary *rotatedHalfRenderArea =
new TIntermBinary(EOpMatrixTimesVector, getHalfRenderAreaRotationMatrix(), halfRenderArea);
return rotatedHalfRenderArea;
}
} // namespace sh } // namespace sh
...@@ -38,12 +38,18 @@ class FlipRotateSpecConst ...@@ -38,12 +38,18 @@ class FlipRotateSpecConst
TIntermTyped *getFlipY(); TIntermTyped *getFlipY();
TIntermTyped *getNegFlipY(); TIntermTyped *getNegFlipY();
TIntermTyped *getFragRotationMultiplyFlipXY(); TIntermTyped *getFragRotationMultiplyFlipXY();
TIntermBinary *getHalfRenderArea();
TIntermTyped *getHalfRenderAreaRotationMatrix();
void generateSymbol(TSymbolTable *symbolTable); void generateSymbol(TSymbolTable *symbolTable);
void outputLayoutString(TInfoSinkBase &sink) const; void outputLayoutString(TInfoSinkBase &sink) const;
SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; } SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; }
private: private:
TIntermSymbol *getDrawableWidth();
TIntermSymbol *getDrawableHeight();
TSymbolTable *mSymbolTable;
TIntermSymbol *mSpecConstSymbol; TIntermSymbol *mSpecConstSymbol;
// Bit is set if YFlip or Rotation has been used // Bit is set if YFlip or Rotation has been used
SpecConstUsageBits mUsageBits; SpecConstUsageBits mUsageBits;
......
...@@ -1089,8 +1089,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1089,8 +1089,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
{ {
const vk::GraphicsPipelineDesc *descPtr; const vk::GraphicsPipelineDesc *descPtr;
// The desc's surface rotation specialization constant depends on both program's // The desc's specialization constant depends on program's
// specConstUsageBits and drawable. We need to update it if program has changed. // specConstUsageBits. We need to update it if program has changed.
SpecConstUsageBits usageBits = getCurrentProgramSpecConstUsageBits(); SpecConstUsageBits usageBits = getCurrentProgramSpecConstUsageBits();
updateGraphicsPipelineDescWithSpecConstUsageBits(usageBits); updateGraphicsPipelineDescWithSpecConstUsageBits(usageBits);
...@@ -3178,6 +3178,19 @@ void ContextVk::updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageB ...@@ -3178,6 +3178,19 @@ void ContextVk::updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageB
// program object will be retrieved. // program object will be retrieved.
mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, rotationAndFlip); mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, rotationAndFlip);
} }
if (usageBits.test(sh::vk::SpecConstUsage::DrawableSize))
{
const gl::Box &dimensions = getState().getDrawFramebuffer()->getDimensions();
mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, dimensions.width,
dimensions.height);
}
else
{
// Always set specialization constant to 1x1 if it is not used so that pipeline program with
// only drawable size difference will be able to be reused.
mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, 1, 1);
}
} }
void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState) void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState)
...@@ -3388,6 +3401,9 @@ void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebuffer ...@@ -3388,6 +3401,9 @@ void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebuffer
invalidateCurrentGraphicsPipeline(); invalidateCurrentGraphicsPipeline();
mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
framebufferVk->getRenderPassDesc()); framebufferVk->getRenderPassDesc());
const gl::Box &dimensions = framebufferVk->getState().getDimensions();
mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, dimensions.width,
dimensions.height);
} }
void ContextVk::invalidateCurrentTransformFeedbackBuffers() void ContextVk::invalidateCurrentTransformFeedbackBuffers()
......
...@@ -679,6 +679,17 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline( ...@@ -679,6 +679,17 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram(); vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
ASSERT(shaderProgram); ASSERT(shaderProgram);
// Drawable size is part of specialization constant, but does not have its own dedicated
// programInfo entry. We pick the programInfo entry based on the mTransformOptions and then
// update drawable width/height specialization constant. It will go through desc matching and if
// spec constant does not match, it will recompile pipeline program.
const vk::PackedExtent &dimensions = desc.getDrawableSize();
shaderProgram->setSpecializationConstant(sh::vk::SpecializationConstantId::DrawableWidth,
dimensions.width);
shaderProgram->setSpecializationConstant(sh::vk::SpecializationConstantId::DrawableHeight,
dimensions.height);
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache)); ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
return shaderProgram->getGraphicsPipeline( return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), *pipelineCache, getPipelineLayout(), desc, contextVk, &contextVk->getRenderPassCache(), *pipelineCache, getPipelineLayout(), desc,
......
...@@ -1202,6 +1202,16 @@ void InitializeSpecializationInfo( ...@@ -1202,6 +1202,16 @@ void InitializeSpecializationInfo(
offsetof(SpecializationConstants, surfaceRotation); offsetof(SpecializationConstants, surfaceRotation);
(*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation); (*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation);
break; break;
case sh::vk::SpecializationConstantId::DrawableWidth:
(*specializationEntriesOut)[id].offset =
offsetof(vk::SpecializationConstants, drawableWidth);
(*specializationEntriesOut)[id].size = sizeof(specConsts.drawableWidth);
break;
case sh::vk::SpecializationConstantId::DrawableHeight:
(*specializationEntriesOut)[id].offset =
offsetof(vk::SpecializationConstants, drawableHeight);
(*specializationEntriesOut)[id].size = sizeof(specConsts.drawableHeight);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -1610,7 +1620,7 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -1610,7 +1620,7 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const ShaderModule *vertexModule, const ShaderModule *vertexModule,
const ShaderModule *fragmentModule, const ShaderModule *fragmentModule,
const ShaderModule *geometryModule, const ShaderModule *geometryModule,
const SpecializationConstants specConsts, const SpecializationConstants &specConsts,
Pipeline *pipelineOut) const Pipeline *pipelineOut) const
{ {
angle::FixedVector<VkPipelineShaderStageCreateInfo, 3> shaderStages; angle::FixedVector<VkPipelineShaderStageCreateInfo, 3> shaderStages;
...@@ -2487,6 +2497,16 @@ void GraphicsPipelineDesc::updateScissor(GraphicsPipelineTransitionBits *transit ...@@ -2487,6 +2497,16 @@ void GraphicsPipelineDesc::updateScissor(GraphicsPipelineTransitionBits *transit
transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, height)); transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, height));
} }
void GraphicsPipelineDesc::updateDrawableSize(GraphicsPipelineTransitionBits *transition,
uint32_t width,
uint32_t height)
{
SetBitField(mDrawableSize.width, width);
SetBitField(mDrawableSize.height, height);
transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, width));
transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, height));
}
void GraphicsPipelineDesc::updateSubpass(GraphicsPipelineTransitionBits *transition, void GraphicsPipelineDesc::updateSubpass(GraphicsPipelineTransitionBits *transition,
uint32_t subpass) uint32_t subpass)
{ {
...@@ -3306,7 +3326,7 @@ angle::Result GraphicsPipelineCache::insertPipeline( ...@@ -3306,7 +3326,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule, const vk::ShaderModule *geometryModule,
const vk::SpecializationConstants specConsts, const vk::SpecializationConstants &specConsts,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut, const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut) vk::PipelineHelper **pipelineOut)
......
...@@ -534,6 +534,12 @@ struct PackedScissor final ...@@ -534,6 +534,12 @@ struct PackedScissor final
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
}; };
struct PackedExtent final
{
uint16_t width;
uint16_t height;
};
// This is invalid value for PackedScissor.x. It is used to indicate scissor is a dynamic state // This is invalid value for PackedScissor.x. It is used to indicate scissor is a dynamic state
constexpr int32_t kDynamicScissorSentinel = std::numeric_limits<decltype(PackedScissor::x)>::max(); constexpr int32_t kDynamicScissorSentinel = std::numeric_limits<decltype(PackedScissor::x)>::max();
...@@ -544,7 +550,7 @@ static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check fail ...@@ -544,7 +550,7 @@ static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check fail
constexpr size_t kGraphicsPipelineDescSumOfSizes = constexpr size_t kGraphicsPipelineDescSumOfSizes =
kVertexInputAttributesSize + kRenderPassDescSize + kPackedRasterizationAndMultisampleStateSize + kVertexInputAttributesSize + kRenderPassDescSize + kPackedRasterizationAndMultisampleStateSize +
kPackedDepthStencilStateSize + kPackedInputAssemblyAndColorBlendStateSize + sizeof(VkViewport) + kPackedDepthStencilStateSize + kPackedInputAssemblyAndColorBlendStateSize + sizeof(VkViewport) +
sizeof(PackedScissor); sizeof(PackedScissor) + sizeof(PackedExtent);
// Number of dirty bits in the dirty bit set. // Number of dirty bits in the dirty bit set.
constexpr size_t kGraphicsPipelineDirtyBitBytes = 4; constexpr size_t kGraphicsPipelineDirtyBitBytes = 4;
...@@ -592,7 +598,7 @@ class GraphicsPipelineDesc final ...@@ -592,7 +598,7 @@ class GraphicsPipelineDesc final
const ShaderModule *vertexModule, const ShaderModule *vertexModule,
const ShaderModule *fragmentModule, const ShaderModule *fragmentModule,
const ShaderModule *geometryModule, const ShaderModule *geometryModule,
const SpecializationConstants specConsts, const SpecializationConstants &specConsts,
Pipeline *pipelineOut) const; Pipeline *pipelineOut) const;
// Vertex input state. For ES 3.1 this should be separated into binding and attribute. // Vertex input state. For ES 3.1 this should be separated into binding and attribute.
...@@ -726,6 +732,11 @@ class GraphicsPipelineDesc final ...@@ -726,6 +732,11 @@ class GraphicsPipelineDesc final
mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation); mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation);
} }
void updateDrawableSize(GraphicsPipelineTransitionBits *transition,
uint32_t width,
uint32_t height);
const PackedExtent &getDrawableSize() const { return mDrawableSize; }
private: private:
void updateSubpass(GraphicsPipelineTransitionBits *transition, uint32_t subpass); void updateSubpass(GraphicsPipelineTransitionBits *transition, uint32_t subpass);
...@@ -738,6 +749,7 @@ class GraphicsPipelineDesc final ...@@ -738,6 +749,7 @@ class GraphicsPipelineDesc final
// The special value of .offset.x == INT_MIN for scissor implies dynamic scissor that needs to // The special value of .offset.x == INT_MIN for scissor implies dynamic scissor that needs to
// be set through vkCmdSetScissor. // be set through vkCmdSetScissor.
PackedScissor mScissor; PackedScissor mScissor;
PackedExtent mDrawableSize;
}; };
// Verify the packed pipeline description has no gaps in the packing. // Verify the packed pipeline description has no gaps in the packing.
...@@ -1365,7 +1377,7 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -1365,7 +1377,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule, const vk::ShaderModule *geometryModule,
const vk::SpecializationConstants specConsts, const vk::SpecializationConstants &specConsts,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut, const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut) vk::PipelineHelper **pipelineOut)
...@@ -1394,7 +1406,7 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -1394,7 +1406,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule, const vk::ShaderModule *geometryModule,
const vk::SpecializationConstants specConsts, const vk::SpecializationConstants &specConsts,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut, const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut); vk::PipelineHelper **pipelineOut);
......
...@@ -6964,6 +6964,12 @@ void ShaderProgramHelper::setSpecializationConstant(sh::vk::SpecializationConsta ...@@ -6964,6 +6964,12 @@ void ShaderProgramHelper::setSpecializationConstant(sh::vk::SpecializationConsta
case sh::vk::SpecializationConstantId::SurfaceRotation: case sh::vk::SpecializationConstantId::SurfaceRotation:
mSpecializationConstants.surfaceRotation = value; mSpecializationConstants.surfaceRotation = value;
break; break;
case sh::vk::SpecializationConstantId::DrawableWidth:
mSpecializationConstants.drawableWidth = value;
break;
case sh::vk::SpecializationConstantId::DrawableHeight:
mSpecializationConstants.drawableHeight = value;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -690,6 +690,8 @@ struct SpecializationConstants final ...@@ -690,6 +690,8 @@ struct SpecializationConstants final
{ {
VkBool32 lineRasterEmulation; VkBool32 lineRasterEmulation;
uint32_t surfaceRotation; uint32_t surfaceRotation;
uint32_t drawableWidth;
uint32_t drawableHeight;
}; };
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
......
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