Vulkan: Implement BlendState

This commit is contained in:
Corentin Wallez 2018-02-02 11:26:51 -05:00 committed by Corentin Wallez
parent b0ae792954
commit 5842c71e17
7 changed files with 165 additions and 15 deletions

View File

@ -288,6 +288,8 @@ if (NXT_ENABLE_VULKAN)
target_include_directories(vulkan_autogen PUBLIC ${SRC_DIR}) target_include_directories(vulkan_autogen PUBLIC ${SRC_DIR})
list(APPEND BACKEND_SOURCES list(APPEND BACKEND_SOURCES
${VULKAN_DIR}/BlendStateVk.cpp
${VULKAN_DIR}/BlendStateVk.h
${VULKAN_DIR}/BufferUploader.cpp ${VULKAN_DIR}/BufferUploader.cpp
${VULKAN_DIR}/BufferUploader.h ${VULKAN_DIR}/BufferUploader.h
${VULKAN_DIR}/BufferVk.cpp ${VULKAN_DIR}/BufferVk.cpp

View File

@ -0,0 +1,110 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "backend/vulkan/BlendStateVk.h"
#include "common/Assert.h"
namespace backend { namespace vulkan {
namespace {
VkBlendFactor VulkanBlendFactor(nxt::BlendFactor factor) {
switch (factor) {
case nxt::BlendFactor::Zero:
return VK_BLEND_FACTOR_ZERO;
case nxt::BlendFactor::One:
return VK_BLEND_FACTOR_ONE;
case nxt::BlendFactor::SrcColor:
return VK_BLEND_FACTOR_SRC_COLOR;
case nxt::BlendFactor::OneMinusSrcColor:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
case nxt::BlendFactor::SrcAlpha:
return VK_BLEND_FACTOR_SRC_ALPHA;
case nxt::BlendFactor::OneMinusSrcAlpha:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
case nxt::BlendFactor::DstColor:
return VK_BLEND_FACTOR_DST_COLOR;
case nxt::BlendFactor::OneMinusDstColor:
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
case nxt::BlendFactor::DstAlpha:
return VK_BLEND_FACTOR_DST_ALPHA;
case nxt::BlendFactor::OneMinusDstAlpha:
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
case nxt::BlendFactor::SrcAlphaSaturated:
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
case nxt::BlendFactor::BlendColor:
return VK_BLEND_FACTOR_CONSTANT_COLOR;
case nxt::BlendFactor::OneMinusBlendColor:
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
default:
UNREACHABLE();
}
}
VkBlendOp VulkanBlendOperation(nxt::BlendOperation operation) {
switch (operation) {
case nxt::BlendOperation::Add:
return VK_BLEND_OP_ADD;
case nxt::BlendOperation::Subtract:
return VK_BLEND_OP_SUBTRACT;
case nxt::BlendOperation::ReverseSubtract:
return VK_BLEND_OP_REVERSE_SUBTRACT;
case nxt::BlendOperation::Min:
return VK_BLEND_OP_MIN;
case nxt::BlendOperation::Max:
return VK_BLEND_OP_MAX;
default:
UNREACHABLE();
}
}
VkColorComponentFlagBits VulkanColorWriteMask(nxt::ColorWriteMask mask) {
// Vulkan and NXT color write masks match, static assert it and return the mask
static_assert(static_cast<VkColorComponentFlagBits>(nxt::ColorWriteMask::Red) ==
VK_COLOR_COMPONENT_R_BIT,
"");
static_assert(static_cast<VkColorComponentFlagBits>(nxt::ColorWriteMask::Green) ==
VK_COLOR_COMPONENT_G_BIT,
"");
static_assert(static_cast<VkColorComponentFlagBits>(nxt::ColorWriteMask::Blue) ==
VK_COLOR_COMPONENT_B_BIT,
"");
static_assert(static_cast<VkColorComponentFlagBits>(nxt::ColorWriteMask::Alpha) ==
VK_COLOR_COMPONENT_A_BIT,
"");
return static_cast<VkColorComponentFlagBits>(mask);
}
} // anonymous namespace
BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) {
// Fill the "color blend attachment info" that will be copied in an array and chained in
// the pipeline create info.
const auto& info = GetBlendInfo();
mState.blendEnable = info.blendEnabled ? VK_TRUE : VK_FALSE;
mState.srcColorBlendFactor = VulkanBlendFactor(info.colorBlend.srcFactor);
mState.dstColorBlendFactor = VulkanBlendFactor(info.colorBlend.dstFactor);
mState.colorBlendOp = VulkanBlendOperation(info.colorBlend.operation);
mState.srcAlphaBlendFactor = VulkanBlendFactor(info.alphaBlend.srcFactor);
mState.dstAlphaBlendFactor = VulkanBlendFactor(info.alphaBlend.dstFactor);
mState.alphaBlendOp = VulkanBlendOperation(info.alphaBlend.operation);
mState.colorWriteMask = VulkanColorWriteMask(info.colorWriteMask);
}
const VkPipelineColorBlendAttachmentState& BlendState::GetState() const {
return mState;
}
}} // namespace backend::vulkan

View File

@ -0,0 +1,39 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BACKEND_VULKAN_BLENDSTATEVK_H_
#define BACKEND_VULKAN_BLENDSTATEVK_H_
#include "backend/BlendState.h"
#include "common/vulkan_platform.h"
namespace backend { namespace vulkan {
class Device;
// Pre-computes the blend state configuration to give to a graphics pipeline create info.
class BlendState : public BlendStateBase {
public:
BlendState(BlendStateBuilder* builder);
const VkPipelineColorBlendAttachmentState& GetState() const;
private:
VkPipelineColorBlendAttachmentState mState;
};
}} // namespace backend::vulkan
#endif // BACKEND_VULKAN_BLENDSTATEVK_H_

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "backend/vulkan/BlendStateVk.h"
#include "backend/vulkan/BufferVk.h" #include "backend/vulkan/BufferVk.h"
#include "backend/vulkan/CommandBufferVk.h" #include "backend/vulkan/CommandBufferVk.h"
#include "backend/vulkan/FramebufferVk.h" #include "backend/vulkan/FramebufferVk.h"

View File

@ -14,6 +14,7 @@
#include "backend/vulkan/RenderPipelineVk.h" #include "backend/vulkan/RenderPipelineVk.h"
#include "backend/vulkan/BlendStateVk.h"
#include "backend/vulkan/FencedDeleter.h" #include "backend/vulkan/FencedDeleter.h"
#include "backend/vulkan/InputStateVk.h" #include "backend/vulkan/InputStateVk.h"
#include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/PipelineLayoutVk.h"
@ -155,28 +156,25 @@ namespace backend { namespace vulkan {
depthStencil.minDepthBounds = 0.0f; depthStencil.minDepthBounds = 0.0f;
depthStencil.maxDepthBounds = 0.0f; depthStencil.maxDepthBounds = 0.0f;
// Even when not using independent blend, we need to provide blend information for every // Initialize the "blend state info" that will be chained in the "create info" from the data
// single attachment. // pre-computed in the BlendState
const auto& subpassInfo = GetRenderPass()->GetSubpassInfo(GetSubPass());
std::array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments; std::array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments;
for (auto& attachment : colorBlendAttachments) { for (uint32_t i : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
attachment.blendEnable = VK_FALSE; colorBlendAttachments[i] = ToBackend(GetBlendState(i))->GetState();
attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.colorBlendOp = VK_BLEND_OP_ADD;
attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.alphaBlendOp = VK_BLEND_OP_ADD;
attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
} }
VkPipelineColorBlendStateCreateInfo colorBlend; VkPipelineColorBlendStateCreateInfo colorBlend;
colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlend.pNext = nullptr; colorBlend.pNext = nullptr;
colorBlend.flags = 0; colorBlend.flags = 0;
// LogicOp isn't supported so we disable it.
colorBlend.logicOpEnable = VK_FALSE; colorBlend.logicOpEnable = VK_FALSE;
colorBlend.logicOp = VK_LOGIC_OP_CLEAR; colorBlend.logicOp = VK_LOGIC_OP_CLEAR;
colorBlend.attachmentCount = kMaxColorAttachments; // TODO(cwallez@chromium.org): Do we allow holes in the color attachments?
colorBlend.attachmentCount = static_cast<uint32_t>(subpassInfo.colorAttachmentsSet.count());
colorBlend.pAttachments = colorBlendAttachments.data(); colorBlend.pAttachments = colorBlendAttachments.data();
// The blend constant is always dynamic so we fill in a dummy value
colorBlend.blendConstants[0] = 0.0f; colorBlend.blendConstants[0] = 0.0f;
colorBlend.blendConstants[1] = 0.0f; colorBlend.blendConstants[1] = 0.0f;
colorBlend.blendConstants[2] = 0.0f; colorBlend.blendConstants[2] = 0.0f;

View File

@ -15,6 +15,7 @@
#include "backend/vulkan/VulkanBackend.h" #include "backend/vulkan/VulkanBackend.h"
#include "backend/Commands.h" #include "backend/Commands.h"
#include "backend/vulkan/BlendStateVk.h"
#include "backend/vulkan/BufferUploader.h" #include "backend/vulkan/BufferUploader.h"
#include "backend/vulkan/BufferVk.h" #include "backend/vulkan/BufferVk.h"
#include "backend/vulkan/CommandBufferVk.h" #include "backend/vulkan/CommandBufferVk.h"

View File

@ -19,7 +19,6 @@
#include "backend/BindGroup.h" #include "backend/BindGroup.h"
#include "backend/BindGroupLayout.h" #include "backend/BindGroupLayout.h"
#include "backend/BlendState.h"
#include "backend/ComputePipeline.h" #include "backend/ComputePipeline.h"
#include "backend/DepthStencilState.h" #include "backend/DepthStencilState.h"
#include "backend/Device.h" #include "backend/Device.h"
@ -38,7 +37,7 @@ namespace backend { namespace vulkan {
using BindGroup = BindGroupBase; using BindGroup = BindGroupBase;
using BindGroupLayout = BindGroupLayoutBase; using BindGroupLayout = BindGroupLayoutBase;
using BlendState = BlendStateBase; class BlendState;
class Buffer; class Buffer;
using BufferView = BufferViewBase; using BufferView = BufferViewBase;
class CommandBuffer; class CommandBuffer;