Use dynamic state from vulkan pipelines
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1813913002 Review URL: https://codereview.chromium.org/1813913002
This commit is contained in:
parent
58fc94e55f
commit
470d77a1d7
@ -9,6 +9,7 @@
|
||||
|
||||
#include "GrVkFramebuffer.h"
|
||||
#include "GrVkImageView.h"
|
||||
#include "GrVkPipeline.h"
|
||||
#include "GrVkRenderPass.h"
|
||||
#include "GrVkRenderTarget.h"
|
||||
#include "GrVkProgram.h"
|
||||
@ -40,10 +41,20 @@ GrVkCommandBuffer::~GrVkCommandBuffer() {
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::invalidateState() {
|
||||
fBoundVertexBuffer = 0;
|
||||
fBoundVertexBuffer = VK_NULL_HANDLE;
|
||||
fBoundVertexBufferIsValid = false;
|
||||
fBoundIndexBuffer = 0;
|
||||
fBoundIndexBuffer = VK_NULL_HANDLE;
|
||||
fBoundIndexBufferIsValid = false;
|
||||
|
||||
memset(&fCachedViewport, 0, sizeof(VkViewport));
|
||||
fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0
|
||||
|
||||
memset(&fCachedScissor, 0, sizeof(VkRect2D));
|
||||
fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
fCachedBlendConstant[i] = -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
|
||||
@ -355,6 +366,15 @@ void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
|
||||
program->addUniformResources(*this);
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) {
|
||||
SkASSERT(fIsActive);
|
||||
SkASSERT(fActiveRenderPass);
|
||||
GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline()));
|
||||
addResource(pipeline);
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu,
|
||||
uint32_t indexCount,
|
||||
uint32_t instanceCount,
|
||||
@ -384,3 +404,42 @@ void GrVkCommandBuffer::draw(const GrVkGpu* gpu,
|
||||
firstVertex,
|
||||
firstInstance));
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::setViewport(const GrVkGpu* gpu,
|
||||
uint32_t firstViewport,
|
||||
uint32_t viewportCount,
|
||||
const VkViewport* viewports) {
|
||||
SkASSERT(fIsActive);
|
||||
SkASSERT(1 == viewportCount);
|
||||
if (memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) {
|
||||
GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer,
|
||||
firstViewport,
|
||||
viewportCount,
|
||||
viewports));
|
||||
fCachedViewport = viewports[0];
|
||||
}
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::setScissor(const GrVkGpu* gpu,
|
||||
uint32_t firstScissor,
|
||||
uint32_t scissorCount,
|
||||
const VkRect2D* scissors) {
|
||||
SkASSERT(fIsActive);
|
||||
SkASSERT(1 == scissorCount);
|
||||
if (memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) {
|
||||
GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer,
|
||||
firstScissor,
|
||||
scissorCount,
|
||||
scissors));
|
||||
fCachedScissor = scissors[0];
|
||||
}
|
||||
}
|
||||
|
||||
void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu,
|
||||
const float blendConstants[4]) {
|
||||
SkASSERT(fIsActive);
|
||||
if (memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) {
|
||||
GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants));
|
||||
memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,11 @@
|
||||
#define GrVkCommandBuffer_DEFINED
|
||||
|
||||
#include "GrVkGpu.h"
|
||||
#include "GrVkPipeline.h"
|
||||
#include "GrVkResource.h"
|
||||
#include "GrVkUtil.h"
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
class GrVkPipeline;
|
||||
class GrVkRenderPass;
|
||||
class GrVkRenderTarget;
|
||||
class GrVkTransferBuffer;
|
||||
@ -38,15 +38,6 @@ public:
|
||||
void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync);
|
||||
bool finished(const GrVkGpu* gpu) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// CommandBuffer State/Object bindings
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
void bindPipeline(const GrVkGpu* gpu) const;
|
||||
void bindDynamicState(const GrVkGpu* gpu) const;
|
||||
void bindDescriptorSet(const GrVkGpu* gpu) const;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// CommandBuffer commands
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -91,13 +82,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) {
|
||||
GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline()));
|
||||
addResource(pipeline);
|
||||
}
|
||||
|
||||
void bindDescriptorSets(const GrVkGpu* gpu,
|
||||
GrVkProgram*,
|
||||
VkPipelineLayout layout,
|
||||
@ -107,6 +91,18 @@ public:
|
||||
uint32_t dynamicOffsetCount,
|
||||
const uint32_t* dynamicOffsets);
|
||||
|
||||
void setViewport(const GrVkGpu* gpu,
|
||||
uint32_t firstViewport,
|
||||
uint32_t viewportCount,
|
||||
const VkViewport* viewports);
|
||||
|
||||
void setScissor(const GrVkGpu* gpu,
|
||||
uint32_t firstScissor,
|
||||
uint32_t scissorCount,
|
||||
const VkRect2D* scissors);
|
||||
|
||||
void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
|
||||
|
||||
// Commands that only work outside of a render pass
|
||||
void clearColorImage(const GrVkGpu* gpu,
|
||||
GrVkImage* image,
|
||||
@ -149,6 +145,9 @@ public:
|
||||
int numRects,
|
||||
const VkClearRect* clearRects) const;
|
||||
|
||||
void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
|
||||
|
||||
|
||||
void drawIndexed(const GrVkGpu* gpu,
|
||||
uint32_t indexCount,
|
||||
uint32_t instanceCount,
|
||||
@ -205,6 +204,11 @@ private:
|
||||
// A nullptr means there is no active render pass. The GrVKCommandBuffer does not own the render
|
||||
// pass.
|
||||
const GrVkRenderPass* fActiveRenderPass;
|
||||
|
||||
// Cached values used for dynamic state updates
|
||||
VkViewport fCachedViewport;
|
||||
VkRect2D fCachedScissor;
|
||||
float fCachedBlendConstant[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -1533,6 +1533,9 @@ bool GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
|
||||
(*program)->setData(this, primProc, pipeline);
|
||||
|
||||
(*program)->bind(this, fCurrentCmdBuffer);
|
||||
|
||||
GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1548,6 +1551,8 @@ void GrVkGpu::onDraw(const GrPipeline& pipeline,
|
||||
const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
|
||||
SkASSERT(renderPass);
|
||||
|
||||
fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
|
||||
|
||||
GrVkProgram* program = nullptr;
|
||||
GrPrimitiveType primitiveType = meshes[0].primitiveType();
|
||||
if (!this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass, &program)) {
|
||||
@ -1590,7 +1595,6 @@ void GrVkGpu::onDraw(const GrPipeline& pipeline,
|
||||
false);
|
||||
}
|
||||
|
||||
fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
|
||||
|
||||
for (int i = 0; i < meshCount; ++i) {
|
||||
if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "GrGeometryProcessor.h"
|
||||
#include "GrPipeline.h"
|
||||
|
||||
#include "GrVkCommandBuffer.h"
|
||||
#include "GrVkGpu.h"
|
||||
#include "GrVkProgramDesc.h"
|
||||
#include "GrVkRenderTarget.h"
|
||||
@ -188,52 +188,18 @@ void setup_depth_stencil_state(const GrVkGpu* gpu,
|
||||
void setup_viewport_scissor_state(const GrVkGpu* gpu,
|
||||
const GrPipeline& pipeline,
|
||||
const GrVkRenderTarget* vkRT,
|
||||
VkPipelineViewportStateCreateInfo* viewportInfo,
|
||||
VkViewport* viewport,
|
||||
VkRect2D* scissor) {
|
||||
VkPipelineViewportStateCreateInfo* viewportInfo) {
|
||||
memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
|
||||
viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewportInfo->pNext = nullptr;
|
||||
viewportInfo->flags = 0;
|
||||
|
||||
viewport->x = 0.0f;
|
||||
viewport->y = 0.0f;
|
||||
viewport->width = SkIntToScalar(vkRT->width());
|
||||
viewport->height = SkIntToScalar(vkRT->height());
|
||||
viewport->minDepth = 0.0f;
|
||||
viewport->maxDepth = 1.0f;
|
||||
viewportInfo->viewportCount = 1;
|
||||
viewportInfo->pViewports = viewport;
|
||||
viewportInfo->pViewports = nullptr; // This is set dynamically
|
||||
|
||||
const GrScissorState& scissorState = pipeline.getScissorState();
|
||||
if (scissorState.enabled() &&
|
||||
!scissorState.rect().contains(0, 0, vkRT->width(), vkRT->height())) {
|
||||
// This all assumes the scissorState has previously been clipped to the device space render
|
||||
// target.
|
||||
scissor->offset.x = scissorState.rect().fLeft;
|
||||
scissor->extent.width = scissorState.rect().width();
|
||||
if (kTopLeft_GrSurfaceOrigin == vkRT->origin()) {
|
||||
scissor->offset.y = scissorState.rect().fTop;
|
||||
} else {
|
||||
SkASSERT(kBottomLeft_GrSurfaceOrigin == vkRT->origin());
|
||||
scissor->offset.y = vkRT->height() - scissorState.rect().fBottom;
|
||||
}
|
||||
scissor->extent.height = scissorState.rect().height();
|
||||
viewportInfo->scissorCount = 1;
|
||||
viewportInfo->pScissors = nullptr; // This is set dynamically
|
||||
|
||||
viewportInfo->scissorCount = 1;
|
||||
viewportInfo->pScissors = scissor;
|
||||
SkASSERT(scissor->offset.x >= 0);
|
||||
SkASSERT(scissor->offset.x + scissor->extent.width <= (uint32_t)vkRT->width());
|
||||
SkASSERT(scissor->offset.y >= 0);
|
||||
SkASSERT(scissor->offset.y + scissor->extent.height <= (uint32_t)vkRT->height());
|
||||
} else {
|
||||
scissor->extent.width = vkRT->width();
|
||||
scissor->extent.height = vkRT->height();
|
||||
scissor->offset.x = 0;
|
||||
scissor->offset.y = 0;
|
||||
viewportInfo->scissorCount = 1;
|
||||
viewportInfo->pScissors = scissor;
|
||||
}
|
||||
SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
|
||||
}
|
||||
|
||||
@ -381,9 +347,7 @@ void setup_color_blend_state(const GrVkGpu* gpu,
|
||||
colorBlendInfo->logicOpEnable = VK_FALSE;
|
||||
colorBlendInfo->attachmentCount = 1;
|
||||
colorBlendInfo->pAttachments = attachmentState;
|
||||
if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
|
||||
GrColorToRGBAFloat(blendInfo.fBlendConstant, colorBlendInfo->blendConstants);
|
||||
}
|
||||
// colorBlendInfo->blendConstants is set dynamically
|
||||
}
|
||||
|
||||
VkCullModeFlags draw_face_to_vk_cull_mode(GrPipelineBuilder::DrawFace drawFace) {
|
||||
@ -422,11 +386,17 @@ void setup_raster_state(const GrVkGpu* gpu,
|
||||
|
||||
void setup_dynamic_state(const GrVkGpu* gpu,
|
||||
const GrPipeline& pipeline,
|
||||
VkPipelineDynamicStateCreateInfo* dynamicInfo) {
|
||||
VkPipelineDynamicStateCreateInfo* dynamicInfo,
|
||||
VkDynamicState* dynamicStates) {
|
||||
memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
|
||||
dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
// TODO: mask out any state we might want to set dynamically
|
||||
dynamicInfo->dynamicStateCount = 0;
|
||||
dynamicInfo->pNext = VK_NULL_HANDLE;
|
||||
dynamicInfo->flags = 0;
|
||||
dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
|
||||
dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
|
||||
dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
|
||||
dynamicInfo->dynamicStateCount = 3;
|
||||
dynamicInfo->pDynamicStates = dynamicStates;
|
||||
}
|
||||
|
||||
GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
|
||||
@ -454,9 +424,7 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
|
||||
GrRenderTarget* rt = pipeline.getRenderTarget();
|
||||
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
|
||||
VkPipelineViewportStateCreateInfo viewportInfo;
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo, &viewport, &scissor);
|
||||
setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo);
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleInfo;
|
||||
setup_multisample_state(pipeline, &multisampleInfo);
|
||||
@ -469,8 +437,9 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
|
||||
VkPipelineRasterizationStateCreateInfo rasterInfo;
|
||||
setup_raster_state(gpu, pipeline, &rasterInfo);
|
||||
|
||||
VkDynamicState dynamicStates[3];
|
||||
VkPipelineDynamicStateCreateInfo dynamicInfo;
|
||||
setup_dynamic_state(gpu, pipeline, &dynamicInfo);
|
||||
setup_dynamic_state(gpu, pipeline, &dynamicInfo, dynamicStates);
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
|
||||
memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
|
||||
@ -511,3 +480,77 @@ void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const {
|
||||
}
|
||||
|
||||
|
||||
void set_dynamic_scissor_state(GrVkGpu* gpu,
|
||||
GrVkCommandBuffer* cmdBuffer,
|
||||
const GrPipeline& pipeline,
|
||||
const GrRenderTarget& target) {
|
||||
// We always use one scissor and if it is disabled we just make it the size of the RT
|
||||
const GrScissorState& scissorState = pipeline.getScissorState();
|
||||
VkRect2D scissor;
|
||||
if (scissorState.enabled() &&
|
||||
!scissorState.rect().contains(0, 0, target.width(), target.height())) {
|
||||
// This all assumes the scissorState has previously been clipped to the device space render
|
||||
// target.
|
||||
scissor.offset.x = scissorState.rect().fLeft;
|
||||
scissor.extent.width = scissorState.rect().width();
|
||||
if (kTopLeft_GrSurfaceOrigin == target.origin()) {
|
||||
scissor.offset.y = scissorState.rect().fTop;
|
||||
} else {
|
||||
SkASSERT(kBottomLeft_GrSurfaceOrigin == target.origin());
|
||||
scissor.offset.y = target.height() - scissorState.rect().fBottom;
|
||||
}
|
||||
scissor.extent.height = scissorState.rect().height();
|
||||
|
||||
SkASSERT(scissor.offset.x >= 0);
|
||||
SkASSERT(scissor.offset.x + scissor.extent.width <= (uint32_t)target.width());
|
||||
SkASSERT(scissor.offset.y >= 0);
|
||||
SkASSERT(scissor.offset.y + scissor.extent.height <= (uint32_t)target.height());
|
||||
} else {
|
||||
scissor.extent.width = target.width();
|
||||
scissor.extent.height = target.height();
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
}
|
||||
cmdBuffer->setScissor(gpu, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
void set_dynamic_viewport_state(GrVkGpu* gpu,
|
||||
GrVkCommandBuffer* cmdBuffer,
|
||||
const GrRenderTarget& target) {
|
||||
// We always use one viewport the size of the RT
|
||||
VkViewport viewport;
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = SkIntToScalar(target.width());
|
||||
viewport.height = SkIntToScalar(target.height());
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
cmdBuffer->setViewport(gpu, 0, 1, &viewport);
|
||||
}
|
||||
|
||||
void set_dynamic_blend_constant_state(GrVkGpu* gpu,
|
||||
GrVkCommandBuffer* cmdBuffer,
|
||||
const GrPipeline& pipeline) {
|
||||
GrXferProcessor::BlendInfo blendInfo;
|
||||
pipeline.getXferProcessor().getBlendInfo(&blendInfo);
|
||||
GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
|
||||
GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
|
||||
float floatColors[4];
|
||||
if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
|
||||
GrColorToRGBAFloat(blendInfo.fBlendConstant, floatColors);
|
||||
} else {
|
||||
memset(floatColors, 0, 4 * sizeof(float));
|
||||
}
|
||||
cmdBuffer->setBlendConstants(gpu, floatColors);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GrVkPipeline::SetDynamicState(GrVkGpu* gpu,
|
||||
GrVkCommandBuffer* cmdBuffer,
|
||||
const GrPipeline& pipeline) {
|
||||
const GrRenderTarget& target = *pipeline.getRenderTarget();
|
||||
set_dynamic_scissor_state(gpu, cmdBuffer, pipeline, target);
|
||||
set_dynamic_viewport_state(gpu, cmdBuffer, target);
|
||||
set_dynamic_blend_constant_state(gpu, cmdBuffer, pipeline);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
class GrNonInstancedVertices;
|
||||
class GrPipeline;
|
||||
class GrPrimitiveProcessor;
|
||||
class GrVkCommandBuffer;
|
||||
class GrVkGpu;
|
||||
class GrVkRenderPass;
|
||||
|
||||
@ -34,6 +35,9 @@ public:
|
||||
|
||||
VkPipeline pipeline() const { return fPipeline; }
|
||||
|
||||
static void SetDynamicState(GrVkGpu*, GrVkCommandBuffer*, const GrPipeline&);
|
||||
|
||||
|
||||
private:
|
||||
GrVkPipeline(VkPipeline pipeline) : INHERITED(), fPipeline(pipeline) {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user