summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingfeng Yang <lfy@google.com>2021-04-23 14:49:25 -0700
committerLingfeng Yang <lfy@google.com>2021-04-29 09:09:25 -0700
commit8270b2873eecfcd18d1f851fe799fb4689de8bf5 (patch)
treef45feb3be5a423b83760b7f4a1dddbddc3938e2c
parent14f4842ffef73adaf1e80a06f8ff7d0a1bfd3ad1 (diff)
downloadvulkan-cereal-8270b2873eecfcd18d1f851fe799fb4689de8bf5.tar.gz
Native VK Swapchain: rcCompose support (basic)
Basic support for rcCompose. Change-Id: Ib1396654311d97b3bb02620785cf9d2ba958bb40
-rw-r--r--stream-servers/ColorBuffer.cpp2
-rw-r--r--stream-servers/CompositorVk.cpp251
-rw-r--r--stream-servers/CompositorVk.h32
-rw-r--r--stream-servers/DisplayVk.cpp104
-rw-r--r--stream-servers/DisplayVk.h7
-rw-r--r--stream-servers/FrameBuffer.cpp55
-rw-r--r--stream-servers/FrameBuffer.h36
-rw-r--r--stream-servers/PostCommands.h40
-rw-r--r--stream-servers/vulkan/Compositor.vert9
-rw-r--r--stream-servers/vulkan/CompositorVertexShader.h101
-rw-r--r--stream-servers/vulkan/VkAndroidNativeBuffer.cpp5
11 files changed, 474 insertions, 168 deletions
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index b36c8710..a01002f6 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -21,6 +21,8 @@
#include "TextureDraw.h"
#include "TextureResize.h"
#include "YUVConverter.h"
+#include "vulkan/VulkanDispatch.h"
+#include "vulkan/VkCommonOperations.h"
#include "OpenGLESDispatch/DispatchTables.h"
#include "OpenGLESDispatch/EGLDispatch.h"
diff --git a/stream-servers/CompositorVk.cpp b/stream-servers/CompositorVk.cpp
index 7be39256..385e62a3 100644
--- a/stream-servers/CompositorVk.cpp
+++ b/stream-servers/CompositorVk.cpp
@@ -2,7 +2,7 @@
#include <string.h>
-#include <glm/gtx/matrix_transform_2d.hpp>
+#include <glm/gtc/matrix_transform.hpp>
#include <optional>
#include "vulkan/vk_util.h"
@@ -24,13 +24,123 @@ static VkShaderModule createShaderModule(const goldfish_vk::VulkanDispatch &vk,
return res;
}
-Composition::Composition(VkImageView vkImageView, VkSampler vkSampler,
- uint32_t width, uint32_t height)
- : m_vkImageView(vkImageView),
- m_vkSampler(vkSampler),
+Composition::Composition(VkSampler vkSampler, uint32_t width, uint32_t height,
+ const std::vector<ComposeLayerVk>& composeLayers)
+ : m_vkSampler(vkSampler),
m_width(width),
m_height(height),
- m_transform(1.0f) {}
+ m_composeLayers(composeLayers) {
+ setTransforms();
+}
+
+Composition::Composition(VkImageView vkImageView, VkSampler vkSampler, uint32_t width, uint32_t height)
+ : m_vkSampler(vkSampler),
+ m_width(width),
+ m_height(height) {
+
+ ComposeLayerVk composeLayer;
+ composeLayer.imageView = vkImageView;
+ composeLayer.layerInfo =
+ (ComposeLayer){
+ 0,
+ HWC2_COMPOSITION_DEVICE,
+ { 0, 0, static_cast<int>(width), static_cast<int>(height) },
+ { 0.0f, 0.0f, (float)width, (float)height },
+ HWC2_BLEND_MODE_PREMULTIPLIED,
+ 1.0f,
+ { 0, 0, 0, 0},
+ (hwc_transform_t)0 /* transform */
+ };
+ std::vector<ComposeLayerVk> composeLayers = {
+ composeLayer,
+ };
+
+ m_composeLayers = composeLayers;
+ setTransforms();
+}
+
+void Composition::setTransforms() {
+ float pos_scaleX;
+ float pos_scaleY;
+ float pos_trX;
+ float pos_trY;
+
+ float texcoord_scaleX;
+ float texcoord_scaleY;
+ float texcoord_trX;
+ float texcoord_trY;
+
+ float dst_width = (float)m_width;
+ float dst_height = (float)m_height;
+
+ uint32_t i = 0;
+
+ for (const auto& info : m_composeLayers) {
+ uint32_t cbWidth = info.cbWidth;
+ uint32_t cbHeight = info.cbHeight;
+ const auto& li = info.layerInfo;
+ const auto& pos_rect = li.displayFrame;
+ const auto& texcoord_rect = li.crop;
+
+ int pos_width = pos_rect.right - pos_rect.left;
+ int pos_height = pos_rect.bottom - pos_rect.top;
+
+ pos_scaleX = float(pos_width) / dst_width;
+ pos_scaleY = float(pos_height) / dst_height;
+
+ pos_trX = -1.0f + pos_scaleX + 2.0f * float(pos_rect.left) / dst_width;
+ pos_trY = -1.0f + pos_scaleY + 2.0f * float(pos_rect.top) / dst_height;
+
+ texcoord_scaleX = (texcoord_rect.right - texcoord_rect.left) / float(cbWidth);
+ texcoord_scaleY = (texcoord_rect.bottom - texcoord_rect.top) / float(cbHeight);
+
+ texcoord_trX = texcoord_rect.left / float(cbWidth);
+ texcoord_trY = texcoord_rect.top / float(cbHeight);
+
+ float texcoord_rot = 0.0f;
+
+ const float pi = 3.14159265358979324f;
+
+ switch (li.transform) {
+ case HWC_TRANSFORM_ROT_90:
+ texcoord_rot = pi * 0.5f;
+ break;
+ case HWC_TRANSFORM_ROT_180:
+ texcoord_rot = pi;
+ break;
+ case HWC_TRANSFORM_ROT_270:
+ texcoord_rot = pi * 1.5f;
+ break;
+ case HWC_TRANSFORM_FLIP_H:
+ texcoord_scaleX *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_V:
+ texcoord_scaleY *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_H_ROT_90:
+ texcoord_rot = pi * 0.5f;
+ texcoord_scaleX *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_V_ROT_90:
+ texcoord_rot = pi * 0.5f;
+ texcoord_scaleY *= -1.0f;
+ break;
+ default:
+ break;
+
+ }
+
+ m_transformsPerLayer.push_back({
+ glm::translate(glm::mat4(1.0f), glm::vec3(pos_trX, pos_trY, 0.0f)) *
+ glm::scale(glm::mat4(1.0f), glm::vec3(pos_scaleX, pos_scaleY, 1.0f)),
+ glm::translate(glm::mat4(1.0f), glm::vec3(texcoord_trX, texcoord_trY, 0.0f)) *
+ glm::scale(glm::mat4(1.0f), glm::vec3(texcoord_scaleX, texcoord_scaleY, 1.0f)) *
+ glm::rotate(glm::mat4(1.0f), texcoord_rot, glm::vec3(0.0f, 0.0f, 1.0f)),
+ });
+
+ ++i;
+ }
+}
const std::vector<CompositorVk::Vertex> CompositorVk::k_vertices = {
{{-1.0f, -1.0f}, {0.0f, 0.0f}},
@@ -84,6 +194,10 @@ CompositorVk::CompositorVk(const goldfish_vk::VulkanDispatch &vk,
m_emptyCompositionVkSampler(VK_NULL_HANDLE),
m_currentCompositions(0),
m_uniformStorage({VK_NULL_HANDLE, VK_NULL_HANDLE, nullptr, 0}) {
+
+ (void)m_renderTargetWidth;
+ (void)m_renderTargetHeight;
+
VkPhysicalDeviceProperties physicalDeviceProperties;
m_vk.vkGetPhysicalDeviceProperties(m_vkPhysicalDevice,
&physicalDeviceProperties);
@@ -203,12 +317,12 @@ void CompositorVk::setUpGraphicsPipeline(uint32_t width, uint32_t height,
VkPipelineColorBlendAttachmentState colorBlendAttachment = {
.blendEnable = VK_TRUE,
- .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
+ .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.colorBlendOp = VK_BLEND_OP_ADD,
- .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
- .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
- .alphaBlendOp = VK_BLEND_OP_MAX,
+ .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
+ .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ .alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
@@ -433,35 +547,39 @@ void CompositorVk::setUpFramebuffers(
}
}
+static const uint32_t kMaxLayersPerFrame = 10;
+
void CompositorVk::setUpDescriptorSets() {
uint32_t numOfFrames =
static_cast<uint32_t>(m_renderTargetVkFrameBuffers.size());
+ uint32_t setsPerDescriptorType = numOfFrames * kMaxLayersPerFrame;
+
VkDescriptorPoolSize descriptorPoolSizes[2] = {
{.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .descriptorCount = numOfFrames},
+ .descriptorCount = setsPerDescriptorType},
{.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .descriptorCount = numOfFrames}};
+ .descriptorCount = setsPerDescriptorType}};
VkDescriptorPoolCreateInfo descriptorPoolCi = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT,
- .maxSets = static_cast<uint32_t>(numOfFrames),
+ .maxSets = static_cast<uint32_t>(setsPerDescriptorType),
.poolSizeCount = static_cast<uint32_t>(std::size(descriptorPoolSizes)),
.pPoolSizes = descriptorPoolSizes};
VK_CHECK(m_vk.vkCreateDescriptorPool(m_vkDevice, &descriptorPoolCi, nullptr,
&m_vkDescriptorPool));
- std::vector<VkDescriptorSetLayout> layouts(numOfFrames,
+ std::vector<VkDescriptorSetLayout> layouts(setsPerDescriptorType,
m_vkDescriptorSetLayout);
VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = m_vkDescriptorPool,
- .descriptorSetCount = numOfFrames,
+ .descriptorSetCount = setsPerDescriptorType,
.pSetLayouts = layouts.data()};
- m_vkDescriptorSets.resize(numOfFrames);
+ m_vkDescriptorSets.resize(setsPerDescriptorType);
VK_CHECK(m_vk.vkAllocateDescriptorSets(m_vkDevice, &descriptorSetAllocInfo,
m_vkDescriptorSets.data()));
- for (size_t i = 0; i < numOfFrames; i++) {
+ for (size_t i = 0; i < setsPerDescriptorType; i++) {
VkDescriptorBufferInfo bufferInfo = {
.buffer = m_uniformStorage.m_vkBuffer,
.offset = i * m_uniformStorage.m_stride,
@@ -514,11 +632,13 @@ void CompositorVk::setUpCommandBuffers(uint32_t width, uint32_t height) {
offsets);
m_vk.vkCmdBindIndexBuffer(cmdBuffer, m_indexVkBuffer, 0,
VK_INDEX_TYPE_UINT16);
- m_vk.vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- m_vkPipelineLayout, 0, 1,
- &m_vkDescriptorSets[i], 0, nullptr);
- m_vk.vkCmdDrawIndexed(
- cmdBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
+ for (uint32_t j = 0; j < kMaxLayersPerFrame; ++j) {
+ m_vk.vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ m_vkPipelineLayout, 0, 1,
+ &m_vkDescriptorSets[i * kMaxLayersPerFrame + j], 0, nullptr);
+ m_vk.vkCmdDrawIndexed(
+ cmdBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
+ }
m_vk.vkCmdEndRenderPass(cmdBuffer);
VK_CHECK(m_vk.vkEndCommandBuffer(cmdBuffer));
@@ -617,7 +737,7 @@ void CompositorVk::setUpEmptyComposition(VkFormat format) {
void CompositorVk::setUpUniformBuffers() {
auto numOfFrames = m_renderTargetVkFrameBuffers.size();
- VkDeviceSize size = m_uniformStorage.m_stride * numOfFrames;
+ VkDeviceSize size = m_uniformStorage.m_stride * numOfFrames * kMaxLayersPerFrame;
auto maybeBuffer = createBuffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
@@ -677,46 +797,51 @@ VkCommandBuffer CompositorVk::getCommandBuffer(uint32_t i) const {
return m_vkCommandBuffers[i];
}
-void CompositorVk::setComposition(uint32_t i,
+void CompositorVk::setComposition(uint32_t rtIndex,
std::unique_ptr<Composition> &&composition) {
- m_currentCompositions[i] = std::move(composition);
- const auto &currentComposition = *m_currentCompositions[i];
- VkDescriptorImageInfo imageInfo = {
- .sampler = currentComposition.m_vkSampler,
- .imageView = currentComposition.m_vkImageView,
- .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
- VkWriteDescriptorSet descriptorSetWrite = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = m_vkDescriptorSets[i],
- .dstBinding = 0,
- .dstArrayElement = 0,
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .pImageInfo = &imageInfo};
- m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
-
- auto local2screen = glm::translate(glm::mat3(1.0f), glm::vec2(1.0f, 1.0f));
- local2screen =
- glm::scale(
- glm::mat3(1.0f),
- glm::vec2(static_cast<float>(currentComposition.m_width) / 2.0f,
- static_cast<float>(currentComposition.m_height) / 2.0f)) *
- local2screen;
- auto screen2ndc =
- glm::scale(glm::mat3(1.0f),
- glm::vec2(2.0f / static_cast<float>(m_renderTargetWidth),
- 2.0f / static_cast<float>(m_renderTargetHeight)));
- screen2ndc =
- glm::translate(glm::mat3(1.0f), glm::vec2(-1.0f, -1.0f)) * screen2ndc;
- auto t = screen2ndc * currentComposition.m_transform * local2screen;
- UniformBufferObject ubo{};
- ubo.transform = glm::mat4(glm::vec4(t[0][0], t[0][1], 0.0f, t[0][2]),
- glm::vec4(t[1][0], t[1][1], 0.0f, t[1][2]),
- glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
- glm::vec4(t[2][0], t[2][1], 0.0f, t[2][2]));
- memcpy(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
- i * m_uniformStorage.m_stride,
- &ubo, sizeof(ubo));
+ m_currentCompositions[rtIndex] = std::move(composition);
+ const auto &currentComposition = *m_currentCompositions[rtIndex];
+
+ memset(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
+ (rtIndex * kMaxLayersPerFrame + 0) * m_uniformStorage.m_stride,
+ 0,
+ sizeof(Composition::LayerTransform) * kMaxLayersPerFrame);
+
+ for (size_t i = 0; i < currentComposition.m_composeLayers.size(); ++i) {
+ VkDescriptorImageInfo imageInfo = {
+ .sampler = currentComposition.m_vkSampler,
+ .imageView = currentComposition.m_composeLayers[i].imageView,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
+ VkWriteDescriptorSet descriptorSetWrite = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = m_vkDescriptorSets[rtIndex * kMaxLayersPerFrame + i],
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &imageInfo};
+ m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
+ memcpy(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
+ (rtIndex * kMaxLayersPerFrame + i) * m_uniformStorage.m_stride,
+ currentComposition.m_transformsPerLayer.data() + i,
+ sizeof(Composition::LayerTransform));
+ }
+
+ for (size_t i = currentComposition.m_composeLayers.size(); i < kMaxLayersPerFrame; ++i) {
+ VkDescriptorImageInfo imageInfo = {
+ .sampler = m_emptyCompositionVkSampler,
+ .imageView = m_emptyCompositionVkImageView,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
+ VkWriteDescriptorSet descriptorSetWrite = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = m_vkDescriptorSets[rtIndex * kMaxLayersPerFrame + i],
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &imageInfo};
+ m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
+ }
}
VkVertexInputBindingDescription CompositorVk::Vertex::getBindingDescription() {
@@ -737,4 +862,4 @@ CompositorVk::Vertex::getAttributeDescription() {
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(struct Vertex, texPos)}};
-} \ No newline at end of file
+}
diff --git a/stream-servers/CompositorVk.h b/stream-servers/CompositorVk.h
index 91551574..062c4881 100644
--- a/stream-servers/CompositorVk.h
+++ b/stream-servers/CompositorVk.h
@@ -12,19 +12,34 @@
#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
#include "vulkan/vk_util.h"
+#include "Hwc2.h"
+
+class ComposeLayerVk {
+public:
+ VkImageView imageView;
+ uint32_t cbWidth;
+ uint32_t cbHeight;
+ ComposeLayer layerInfo;
+};
+
class Composition {
- public:
- VkImageView m_vkImageView;
+public:
VkSampler m_vkSampler;
uint32_t m_width;
uint32_t m_height;
- // transform matrix in screen coordinates
- glm::mat3 m_transform;
+ std::vector<ComposeLayerVk> m_composeLayers;
+ struct LayerTransform {
+ glm::mat4 pos;
+ glm::mat4 texcoord;
+ };
+ std::vector<LayerTransform> m_transformsPerLayer;
Composition() = delete;
- explicit Composition(VkImageView, VkSampler, uint32_t width,
- uint32_t height);
+ explicit Composition(VkSampler, uint32_t width, uint32_t height, const std::vector<ComposeLayerVk>& composeLayers);
+ explicit Composition(VkImageView, VkSampler, uint32_t width, uint32_t height);
+private:
+ void setTransforms();
};
struct CompositorVkBase
@@ -117,7 +132,8 @@ class CompositorVk : protected CompositorVkBase {
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize) const;
struct UniformBufferObject {
- alignas(16) glm::mat4 transform;
+ alignas(16) glm::mat4 pos_transform;
+ alignas(16) glm::mat4 texcoord_transform;
};
struct Vertex {
@@ -149,4 +165,4 @@ class CompositorVk : protected CompositorVkBase {
} m_uniformStorage;
};
-#endif /* COMPOSITOR_VK_H */ \ No newline at end of file
+#endif /* COMPOSITOR_VK_H */
diff --git a/stream-servers/DisplayVk.cpp b/stream-servers/DisplayVk.cpp
index 62fc66c7..f49b5910 100644
--- a/stream-servers/DisplayVk.cpp
+++ b/stream-servers/DisplayVk.cpp
@@ -2,8 +2,8 @@
#include <glm/glm.hpp>
#include <glm/gtx/matrix_transform_2d.hpp>
-
#include "ErrorLog.h"
+#include "Hwc2.h"
DisplayVk::DisplayVk(const goldfish_vk::VulkanDispatch &vk,
VkPhysicalDevice vkPhysicalDevice,
@@ -121,6 +121,11 @@ void DisplayVk::post(
__FUNCTION__, __FILE__, static_cast<int>(__LINE__));
return;
}
+
+ if (!displayBufferPtr) {
+ return;
+ }
+
auto &surfaceState = *m_surfaceState;
const auto &db = *displayBufferPtr;
@@ -142,12 +147,6 @@ void DisplayVk::post(
}
auto composition = std::make_unique<Composition>(
db.m_vkImageView, m_compositionVkSampler, db.m_width, db.m_height);
- composition->m_transform =
- glm::scale(glm::mat3(1.0),
- glm::vec2(static_cast<float>(surfaceState.m_width) /
- static_cast<float>(db.m_width),
- static_cast<float>(surfaceState.m_height) /
- static_cast<float>(db.m_height)));
m_compositorVk->setComposition(imageIndex, std::move(composition));
surfaceState.m_prevDisplayBuffer = displayBufferPtr;
}
@@ -180,6 +179,95 @@ void DisplayVk::post(
VK_TRUE, UINT64_MAX));
}
+void DisplayVk::compose(
+ const Post& postCmd,
+ const std::vector<std::shared_ptr<DisplayBufferInfo>>& composeBuffers,
+ const std::shared_ptr<DisplayBufferInfo>& displayBufferPtr) {
+ ComposeDevice_v2* composeDevice = (ComposeDevice_v2*)(postCmd.composeBuffer.data());
+ uint32_t bufferSize = (uint32_t)postCmd.composeBuffer.size();
+ ComposeLayer* l = (ComposeLayer*)composeDevice->layer;
+
+ std::vector<ComposeLayerVk> composeLayers;
+ for (int i = 0; i < composeDevice->numLayers; ++i, ++l) {
+ ComposeLayerVk cl;
+ if (!composeBuffers[i]) {
+ fprintf(stderr, "%s: warning: null ptr passed to compose bufer\n", __func__);
+ continue;
+ }
+ cl.imageView = composeBuffers[i]->m_vkImageView;
+ cl.cbWidth = composeBuffers[i]->m_width;
+ cl.cbHeight = composeBuffers[i]->m_height;
+ cl.layerInfo = *l;
+ composeLayers.push_back(cl);
+ }
+
+ if (composeLayers.empty()) {
+ return;
+ }
+
+ if (m_swapChainStateVk == nullptr || m_compositorVk == nullptr) {
+ ERR("%s(%s:%d): Haven't bound to a surface, can't post color buffer.\n",
+ __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
+ return;
+ }
+
+ if (!displayBufferPtr) {
+ return;
+ }
+
+ auto &surfaceState = *m_surfaceState;
+ const auto &db = *displayBufferPtr;
+
+ VK_CHECK(m_vk.vkWaitForFences(m_vkDevice, 1, &m_frameDrawCompleteFence,
+ VK_TRUE, UINT64_MAX));
+ uint32_t imageIndex;
+ VK_CHECK(m_vk.vkAcquireNextImageKHR(
+ m_vkDevice, m_swapChainStateVk->getSwapChain(), UINT64_MAX,
+ m_imageReadySem, VK_NULL_HANDLE, &imageIndex));
+ auto maybePrevDisplayBuffer = surfaceState.m_prevDisplayBuffer.lock();
+
+ if (!canComposite(db.m_vkFormat)) {
+ ERR("%s(%s:%d): Can't composite the DisplayBuffer(0x%" PRIxPTR
+ "). The image(VkFormat = %" PRIu64 ") can be sampled from.\n",
+ __FUNCTION__, __FILE__, static_cast<int>(__LINE__),
+ reinterpret_cast<uintptr_t>(displayBufferPtr.get()),
+ static_cast<uint64_t>(db.m_vkFormat));
+ return;
+ }
+
+ auto composition = std::make_unique<Composition>(
+ m_compositionVkSampler, db.m_width, db.m_height, composeLayers);
+ m_compositorVk->setComposition(imageIndex, std::move(composition));
+ surfaceState.m_prevDisplayBuffer = displayBufferPtr;
+
+ auto cmdBuff = m_compositorVk->getCommandBuffer(imageIndex);
+
+ VK_CHECK(m_vk.vkResetFences(m_vkDevice, 1, &m_frameDrawCompleteFence));
+ VkPipelineStageFlags waitStages[] = {
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
+ VkSubmitInfo submitInfo = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &m_imageReadySem,
+ .pWaitDstStageMask = waitStages,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &cmdBuff,
+ .signalSemaphoreCount = 1,
+ .pSignalSemaphores = &m_frameDrawCompleteSem};
+ VK_CHECK(m_vk.vkQueueSubmit(m_compositorVkQueue, 1, &submitInfo,
+ m_frameDrawCompleteFence));
+
+ auto swapChain = m_swapChainStateVk->getSwapChain();
+ VkPresentInfoKHR presentInfo = {.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &m_frameDrawCompleteSem,
+ .swapchainCount = 1,
+ .pSwapchains = &swapChain,
+ .pImageIndices = &imageIndex};
+ VK_CHECK(m_vk.vkQueuePresentKHR(m_swapChainVkQueue, &presentInfo));
+ VK_CHECK(m_vk.vkWaitForFences(m_vkDevice, 1, &m_frameDrawCompleteFence,
+ VK_TRUE, UINT64_MAX));
+}
+
bool DisplayVk::canComposite(VkFormat format) {
auto it = m_canComposite.find(format);
if (it != m_canComposite.end()) {
@@ -223,4 +311,4 @@ DisplayVk::DisplayBufferInfo::DisplayBufferInfo(
DisplayVk::DisplayBufferInfo::~DisplayBufferInfo() {
m_vk.vkDestroyImageView(m_vkDevice, m_vkImageView, nullptr);
-} \ No newline at end of file
+}
diff --git a/stream-servers/DisplayVk.h b/stream-servers/DisplayVk.h
index 88e86c20..4d3d2666 100644
--- a/stream-servers/DisplayVk.h
+++ b/stream-servers/DisplayVk.h
@@ -8,6 +8,7 @@
#include "CompositorVk.h"
#include "RenderContext.h"
#include "SwapChainStateVk.h"
+#include "PostCommands.h"
#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
// The DisplayVk class holds the Vulkan and other states required to draw a
@@ -49,6 +50,10 @@ class DisplayVk {
uint32_t height);
void post(const std::shared_ptr<DisplayBufferInfo> &);
+ void compose(
+ const Post& postCmd, const std::vector<std::shared_ptr<DisplayBufferInfo>>& composeBuffers,
+ const std::shared_ptr<DisplayBufferInfo>& displayBuffer);
+
private:
bool canComposite(VkFormat);
@@ -77,4 +82,4 @@ class DisplayVk {
std::unordered_map<VkFormat, bool> m_canComposite;
};
-#endif \ No newline at end of file
+#endif
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index efee4542..00d4c03f 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -757,7 +757,7 @@ FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow)
kFeature_RefCountPipe)),
m_noDelayCloseColorBufferEnabled(feature_is_enabled(
kFeature_NoDelayCloseColorBuffer)),
- m_postThread([this](FrameBuffer::Post&& post) {
+ m_postThread([this](Post&& post) {
return postWorkerFunc(post);
}) {
uint32_t displayId = 0;
@@ -857,7 +857,7 @@ FrameBuffer::postWorkerFunc(const Post& post) {
return WorkerProcessingResult::Continue;
}
-void FrameBuffer::sendPostWorkerCmd(FrameBuffer::Post post) {
+void FrameBuffer::sendPostWorkerCmd(Post post) {
#ifdef __APPLE__
bool postOnlyOnMainThread = m_subWin && (emugl::getRenderer() == SELECTED_RENDERER_HOST);
#else
@@ -2480,7 +2480,12 @@ bool FrameBuffer::postImpl(HandleType p_colorbuffer,
// TODO(kaiyili, b/179481815): make DisplayVk::post asynchronous.
if (m_displayVk != nullptr) {
+ if (m_justVkComposed) {
+ m_justVkComposed = false;
+ goto EXIT;
+ }
m_displayVk->post(c->second.cb->getDisplayBufferVk());
+ m_lastPostedColorBuffer = p_colorbuffer;
goto EXIT;
}
@@ -2784,9 +2789,47 @@ bool FrameBuffer::compose(uint32_t bufferSize, void* buffer, bool needPost) {
composeCmd.composeBuffer.resize(bufferSize);
memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
composeCmd.cmd = PostCmd::Compose;
- sendPostWorkerCmd(composeCmd);
- if (p2->displayId == 0 && needPost) {
- post(p2->targetHandle, false);
+ if (m_displayVk) {
+ ColorBufferMap::iterator c;
+
+ std::vector<ColorBufferPtr> cbs; // Keep ColorBuffers alive
+ std::vector<std::shared_ptr<DisplayVk::DisplayBufferInfo>> composeBuffers;
+ ComposeDevice_v2* composeDevice = (ComposeDevice_v2*)buffer;
+ ComposeLayer* l = (ComposeLayer*)composeDevice->layer;
+ for (int i = 0; i < composeDevice->numLayers; ++i, ++l) {
+ c = m_colorbuffers.find(l->cbHandle);
+ if (c == m_colorbuffers.end()) {
+ composeBuffers.push_back(nullptr);
+ continue;
+ }
+ cbs.push_back(c->second.cb);
+ auto db = c->second.cb->getDisplayBufferVk();
+ if (!db) {
+ mutex.unlock();
+ goldfish_vk::setupVkColorBuffer(l->cbHandle);
+ mutex.lock();
+ db = c->second.cb->getDisplayBufferVk();
+ }
+ composeBuffers.push_back(db);
+ }
+
+ c = m_colorbuffers.find(p2->targetHandle);
+ auto db = c->second.cb->getDisplayBufferVk();
+
+ if (!db) {
+ mutex.unlock();
+ goldfish_vk::setupVkColorBuffer(p2->targetHandle);
+ mutex.lock();
+ db = c->second.cb->getDisplayBufferVk();
+ }
+
+ m_displayVk->compose(composeCmd, composeBuffers, db);
+ m_justVkComposed = true;
+ } else {
+ sendPostWorkerCmd(composeCmd);
+ if (p2->displayId == 0 && needPost) {
+ post(p2->targetHandle, false);
+ }
}
return true;
}
@@ -3222,4 +3265,4 @@ VkImageLayout FrameBuffer::getVkImageLayoutForPresent() const {
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
return VK_IMAGE_LAYOUT_GENERAL;
-} \ No newline at end of file
+}
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index 71ce1ec0..08f4e4dc 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -30,6 +30,7 @@
#include "FbConfig.h"
#include "GLESVersionDetector.h"
#include "Hwc2.h"
+#include "PostCommands.h"
#include "PostWorker.h"
#include "ReadbackWorker.h"
#include "RenderContext.h"
@@ -680,6 +681,9 @@ class FrameBuffer {
TextureDraw* m_textureDraw = nullptr;
EGLConfig m_eglConfig = nullptr;
HandleType m_lastPostedColorBuffer = 0;
+ // With Vulkan swapchain, compose also means to post to the WSI surface.
+ // In this case, don't do anything in the subsequent resource flush.
+ bool m_justVkComposed = false;
float m_zRot = 0;
float m_px = 0;
float m_py = 0;
@@ -755,38 +759,6 @@ class FrameBuffer {
// buffer is already tied to a file descriptor in the guest kernel.
bool m_noDelayCloseColorBufferEnabled = false;
- // Posting
- enum class PostCmd {
- Post = 0,
- Viewport = 1,
- Compose = 2,
- Clear = 3,
- Screenshot = 4,
- Exit = 5,
- };
-
- struct Post {
- PostCmd cmd;
- int composeVersion;
- std::vector<char> composeBuffer;
- union {
- ColorBuffer* cb;
- struct {
- int width;
- int height;
- } viewport;
- struct {
- ColorBuffer* cb;
- int screenwidth;
- int screenheight;
- GLenum format;
- GLenum type;
- int rotation;
- void* pixels;
- } screenshot;
- };
- };
-
std::unique_ptr<PostWorker> m_postWorker = {};
android::base::WorkerThread<Post> m_postThread;
android::base::WorkerProcessingResult postWorkerFunc(const Post& post);
diff --git a/stream-servers/PostCommands.h b/stream-servers/PostCommands.h
new file mode 100644
index 00000000..bcc2c759
--- /dev/null
+++ b/stream-servers/PostCommands.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <vector>
+
+#include <GLES2/gl2.h>
+
+class ColorBuffer;
+
+// Posting
+enum class PostCmd {
+ Post = 0,
+ Viewport = 1,
+ Compose = 2,
+ Clear = 3,
+ Screenshot = 4,
+ Exit = 5,
+};
+
+struct Post {
+ PostCmd cmd;
+ int composeVersion;
+ std::vector<char> composeBuffer;
+ union {
+ ColorBuffer* cb;
+ struct {
+ int width;
+ int height;
+ } viewport;
+ struct {
+ ColorBuffer* cb;
+ int screenwidth;
+ int screenheight;
+ GLenum format;
+ GLenum type;
+ int rotation;
+ void* pixels;
+ } screenshot;
+ };
+};
+
diff --git a/stream-servers/vulkan/Compositor.vert b/stream-servers/vulkan/Compositor.vert
index 5dbefbd4..40702633 100644
--- a/stream-servers/vulkan/Compositor.vert
+++ b/stream-servers/vulkan/Compositor.vert
@@ -2,7 +2,8 @@
#extension GL_ARB_separate_shader_objects : enable
layout(binding = 1) uniform UniformBufferObject {
- mat4 transform;
+ mat4 posTransform;
+ mat4 texcoordTransform;
} ubo;
layout(location = 0) in vec2 inPosition;
@@ -11,6 +12,6 @@ layout(location = 1) in vec2 texCoord;
layout(location = 0) out vec2 fragTexCoord;
void main() {
- gl_Position = vec4((ubo.transform * vec4(inPosition, 0.0, 1.0)).xy, 0.0, 1.0);
- fragTexCoord = texCoord;
-} \ No newline at end of file
+ gl_Position = vec4((ubo.posTransform * vec4(inPosition, 0.0, 1.0)).xy, 0.0, 1.0);
+ fragTexCoord = (ubo.texcoordTransform * vec4(texCoord, 0.0, 1.0)).xy;
+}
diff --git a/stream-servers/vulkan/CompositorVertexShader.h b/stream-servers/vulkan/CompositorVertexShader.h
index b1bbcfe2..d98b6daf 100644
--- a/stream-servers/vulkan/CompositorVertexShader.h
+++ b/stream-servers/vulkan/CompositorVertexShader.h
@@ -20,13 +20,13 @@
#include <stdint.h>
const uint32_t compositorVertexShader[] = {
-0x07230203, 0x00010000, 0x000d000a, 0x0000002b,
+0x07230203, 0x00010000, 0x000d000a, 0x00000033,
0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
0x00000000, 0x0003000e, 0x00000000, 0x00000001,
0x0009000f, 0x00000000, 0x00000004, 0x6e69616d,
0x00000000, 0x0000000d, 0x00000019, 0x00000028,
-0x00000029, 0x00030003, 0x00000002, 0x000001c2,
+0x0000002c, 0x00030003, 0x00000002, 0x000001c2,
0x00090004, 0x415f4c47, 0x735f4252, 0x72617065,
0x5f657461, 0x64616873, 0x6f5f7265, 0x63656a62,
0x00007374, 0x000a0004, 0x475f4c47, 0x4c474f4f,
@@ -45,41 +45,47 @@ const uint32_t compositorVertexShader[] = {
0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e,
0x00030005, 0x0000000d, 0x00000000, 0x00070005,
0x00000011, 0x66696e55, 0x426d726f, 0x65666675,
-0x6a624f72, 0x00746365, 0x00060006, 0x00000011,
-0x00000000, 0x6e617274, 0x726f6673, 0x0000006d,
-0x00030005, 0x00000013, 0x006f6275, 0x00050005,
-0x00000019, 0x6f506e69, 0x69746973, 0x00006e6f,
-0x00060005, 0x00000028, 0x67617266, 0x43786554,
-0x64726f6f, 0x00000000, 0x00050005, 0x00000029,
-0x43786574, 0x64726f6f, 0x00000000, 0x00050048,
-0x0000000b, 0x00000000, 0x0000000b, 0x00000000,
-0x00050048, 0x0000000b, 0x00000001, 0x0000000b,
-0x00000001, 0x00050048, 0x0000000b, 0x00000002,
-0x0000000b, 0x00000003, 0x00050048, 0x0000000b,
-0x00000003, 0x0000000b, 0x00000004, 0x00030047,
-0x0000000b, 0x00000002, 0x00040048, 0x00000011,
-0x00000000, 0x00000005, 0x00050048, 0x00000011,
-0x00000000, 0x00000023, 0x00000000, 0x00050048,
-0x00000011, 0x00000000, 0x00000007, 0x00000010,
-0x00030047, 0x00000011, 0x00000002, 0x00040047,
-0x00000013, 0x00000022, 0x00000000, 0x00040047,
-0x00000013, 0x00000021, 0x00000001, 0x00040047,
-0x00000019, 0x0000001e, 0x00000000, 0x00040047,
-0x00000028, 0x0000001e, 0x00000000, 0x00040047,
-0x00000029, 0x0000001e, 0x00000001, 0x00020013,
-0x00000002, 0x00030021, 0x00000003, 0x00000002,
-0x00030016, 0x00000006, 0x00000020, 0x00040017,
-0x00000007, 0x00000006, 0x00000004, 0x00040015,
-0x00000008, 0x00000020, 0x00000000, 0x0004002b,
-0x00000008, 0x00000009, 0x00000001, 0x0004001c,
-0x0000000a, 0x00000006, 0x00000009, 0x0006001e,
-0x0000000b, 0x00000007, 0x00000006, 0x0000000a,
-0x0000000a, 0x00040020, 0x0000000c, 0x00000003,
-0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d,
-0x00000003, 0x00040015, 0x0000000e, 0x00000020,
-0x00000001, 0x0004002b, 0x0000000e, 0x0000000f,
-0x00000000, 0x00040018, 0x00000010, 0x00000007,
-0x00000004, 0x0003001e, 0x00000011, 0x00000010,
+0x6a624f72, 0x00746365, 0x00070006, 0x00000011,
+0x00000000, 0x54736f70, 0x736e6172, 0x6d726f66,
+0x00000000, 0x00080006, 0x00000011, 0x00000001,
+0x63786574, 0x64726f6f, 0x6e617254, 0x726f6673,
+0x0000006d, 0x00030005, 0x00000013, 0x006f6275,
+0x00050005, 0x00000019, 0x6f506e69, 0x69746973,
+0x00006e6f, 0x00060005, 0x00000028, 0x67617266,
+0x43786554, 0x64726f6f, 0x00000000, 0x00050005,
+0x0000002c, 0x43786574, 0x64726f6f, 0x00000000,
+0x00050048, 0x0000000b, 0x00000000, 0x0000000b,
+0x00000000, 0x00050048, 0x0000000b, 0x00000001,
+0x0000000b, 0x00000001, 0x00050048, 0x0000000b,
+0x00000002, 0x0000000b, 0x00000003, 0x00050048,
+0x0000000b, 0x00000003, 0x0000000b, 0x00000004,
+0x00030047, 0x0000000b, 0x00000002, 0x00040048,
+0x00000011, 0x00000000, 0x00000005, 0x00050048,
+0x00000011, 0x00000000, 0x00000023, 0x00000000,
+0x00050048, 0x00000011, 0x00000000, 0x00000007,
+0x00000010, 0x00040048, 0x00000011, 0x00000001,
+0x00000005, 0x00050048, 0x00000011, 0x00000001,
+0x00000023, 0x00000040, 0x00050048, 0x00000011,
+0x00000001, 0x00000007, 0x00000010, 0x00030047,
+0x00000011, 0x00000002, 0x00040047, 0x00000013,
+0x00000022, 0x00000000, 0x00040047, 0x00000013,
+0x00000021, 0x00000001, 0x00040047, 0x00000019,
+0x0000001e, 0x00000000, 0x00040047, 0x00000028,
+0x0000001e, 0x00000000, 0x00040047, 0x0000002c,
+0x0000001e, 0x00000001, 0x00020013, 0x00000002,
+0x00030021, 0x00000003, 0x00000002, 0x00030016,
+0x00000006, 0x00000020, 0x00040017, 0x00000007,
+0x00000006, 0x00000004, 0x00040015, 0x00000008,
+0x00000020, 0x00000000, 0x0004002b, 0x00000008,
+0x00000009, 0x00000001, 0x0004001c, 0x0000000a,
+0x00000006, 0x00000009, 0x0006001e, 0x0000000b,
+0x00000007, 0x00000006, 0x0000000a, 0x0000000a,
+0x00040020, 0x0000000c, 0x00000003, 0x0000000b,
+0x0004003b, 0x0000000c, 0x0000000d, 0x00000003,
+0x00040015, 0x0000000e, 0x00000020, 0x00000001,
+0x0004002b, 0x0000000e, 0x0000000f, 0x00000000,
+0x00040018, 0x00000010, 0x00000007, 0x00000004,
+0x0004001e, 0x00000011, 0x00000010, 0x00000010,
0x00040020, 0x00000012, 0x00000002, 0x00000011,
0x0004003b, 0x00000012, 0x00000013, 0x00000002,
0x00040020, 0x00000014, 0x00000002, 0x00000010,
@@ -91,7 +97,8 @@ const uint32_t compositorVertexShader[] = {
0x00040020, 0x00000025, 0x00000003, 0x00000007,
0x00040020, 0x00000027, 0x00000003, 0x00000017,
0x0004003b, 0x00000027, 0x00000028, 0x00000003,
-0x0004003b, 0x00000018, 0x00000029, 0x00000001,
+0x0004002b, 0x0000000e, 0x00000029, 0x00000001,
+0x0004003b, 0x00000018, 0x0000002c, 0x00000001,
0x00050036, 0x00000002, 0x00000004, 0x00000000,
0x00000003, 0x000200f8, 0x00000005, 0x00050041,
0x00000014, 0x00000015, 0x00000013, 0x0000000f,
@@ -110,7 +117,17 @@ const uint32_t compositorVertexShader[] = {
0x00000007, 0x00000024, 0x00000022, 0x00000023,
0x0000001b, 0x0000001c, 0x00050041, 0x00000025,
0x00000026, 0x0000000d, 0x0000000f, 0x0003003e,
-0x00000026, 0x00000024, 0x0004003d, 0x00000017,
-0x0000002a, 0x00000029, 0x0003003e, 0x00000028,
-0x0000002a, 0x000100fd, 0x00010038
-}; \ No newline at end of file
+0x00000026, 0x00000024, 0x00050041, 0x00000014,
+0x0000002a, 0x00000013, 0x00000029, 0x0004003d,
+0x00000010, 0x0000002b, 0x0000002a, 0x0004003d,
+0x00000017, 0x0000002d, 0x0000002c, 0x00050051,
+0x00000006, 0x0000002e, 0x0000002d, 0x00000000,
+0x00050051, 0x00000006, 0x0000002f, 0x0000002d,
+0x00000001, 0x00070050, 0x00000007, 0x00000030,
+0x0000002e, 0x0000002f, 0x0000001b, 0x0000001c,
+0x00050091, 0x00000007, 0x00000031, 0x0000002b,
+0x00000030, 0x0007004f, 0x00000017, 0x00000032,
+0x00000031, 0x00000031, 0x00000000, 0x00000001,
+0x0003003e, 0x00000028, 0x00000032, 0x000100fd,
+0x00010038
+};
diff --git a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
index 5bc4f24e..42ea6183 100644
--- a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
+++ b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
@@ -277,10 +277,6 @@ void teardownAndroidNativeBufferImage(
anbInfo->acquireQueueState.teardown(vk, device);
- if (anbInfo->externallyBacked) {
- teardownVkColorBuffer(anbInfo->colorBufferHandle);
- }
-
*anbInfo = {};
}
@@ -399,6 +395,7 @@ void AndroidNativeBufferInfo::QueueState::setup(
void AndroidNativeBufferInfo::QueueState::teardown(
VulkanDispatch* vk, VkDevice device) {
+ if (queue) vk->vkQueueWaitIdle(queue);
if (cb) vk->vkFreeCommandBuffers(device, pool, 1, &cb);
if (pool) vk->vkDestroyCommandPool(device, pool, nullptr);
if (fence) vk->vkDestroyFence(device, fence, nullptr);