1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "VulkanStream.h"
15
16 #include <inttypes.h>
17
18 #include <vector>
19
20 #include "render-utils/IOStream.h"
21 #include "aemu/base/BumpPool.h"
22 #include "host-common/GfxstreamFatalError.h"
23 #include "host-common/feature_control.h"
24
25 namespace gfxstream {
26 namespace vk {
27
28 using emugl::ABORT_REASON_OTHER;
29 using emugl::FatalError;
30
VulkanStream(IOStream * stream,const gfxstream::host::FeatureSet & features)31 VulkanStream::VulkanStream(IOStream* stream, const gfxstream::host::FeatureSet& features) : mStream(stream) {
32 unsetHandleMapping();
33
34 if (features.VulkanNullOptionalStrings.enabled) {
35 mFeatureBits |= VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT;
36 }
37 if (features.VulkanIgnoredHandles.enabled) {
38 mFeatureBits |= VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT;
39 }
40 if (features.VulkanShaderFloat16Int8.enabled) {
41 mFeatureBits |= VULKAN_STREAM_FEATURE_SHADER_FLOAT16_INT8_BIT;
42 }
43 }
44
45 VulkanStream::~VulkanStream() = default;
46
setStream(IOStream * stream)47 void VulkanStream::setStream(IOStream* stream) { mStream = stream; }
48
valid()49 bool VulkanStream::valid() { return true; }
50
alloc(void ** ptrAddr,size_t bytes)51 void VulkanStream::alloc(void** ptrAddr, size_t bytes) {
52 if (!bytes) {
53 *ptrAddr = nullptr;
54 return;
55 }
56
57 *ptrAddr = mPool.alloc(bytes);
58
59 if (!*ptrAddr) {
60 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "alloc failed. Wanted size: " << bytes;
61 }
62 }
63
loadStringInPlace(char ** forOutput)64 void VulkanStream::loadStringInPlace(char** forOutput) {
65 size_t len = getBe32();
66
67 alloc((void**)forOutput, len + 1);
68
69 memset(*forOutput, 0x0, len + 1);
70
71 if (len > 0) read(*forOutput, len);
72 }
73
loadStringArrayInPlace(char *** forOutput)74 void VulkanStream::loadStringArrayInPlace(char*** forOutput) {
75 size_t count = getBe32();
76
77 if (!count) {
78 *forOutput = nullptr;
79 return;
80 }
81
82 alloc((void**)forOutput, count * sizeof(char*));
83
84 char** stringsForOutput = *forOutput;
85
86 for (size_t i = 0; i < count; i++) {
87 loadStringInPlace(stringsForOutput + i);
88 }
89 }
90
loadStringInPlaceWithStreamPtr(char ** forOutput,uint8_t ** streamPtr)91 void VulkanStream::loadStringInPlaceWithStreamPtr(char** forOutput, uint8_t** streamPtr) {
92 uint32_t len;
93 memcpy(&len, *streamPtr, sizeof(uint32_t));
94 *streamPtr += sizeof(uint32_t);
95 android::base::Stream::fromBe32((uint8_t*)&len);
96
97 if (len == UINT32_MAX) {
98 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
99 << "VulkanStream can't allocate UINT32_MAX bytes";
100 }
101
102 alloc((void**)forOutput, len + 1);
103
104 if (len > 0) {
105 memcpy(*forOutput, *streamPtr, len);
106 *streamPtr += len;
107 }
108 (*forOutput)[len] = 0;
109 }
110
loadStringArrayInPlaceWithStreamPtr(char *** forOutput,uint8_t ** streamPtr)111 void VulkanStream::loadStringArrayInPlaceWithStreamPtr(char*** forOutput, uint8_t** streamPtr) {
112 uint32_t count;
113 memcpy(&count, *streamPtr, sizeof(uint32_t));
114 *streamPtr += sizeof(uint32_t);
115 android::base::Stream::fromBe32((uint8_t*)&count);
116
117 if (!count) {
118 *forOutput = nullptr;
119 return;
120 }
121
122 alloc((void**)forOutput, count * sizeof(char*));
123
124 char** stringsForOutput = *forOutput;
125
126 for (size_t i = 0; i < count; i++) {
127 loadStringInPlaceWithStreamPtr(stringsForOutput + i, streamPtr);
128 }
129 }
130
read(void * buffer,size_t size)131 ssize_t VulkanStream::read(void* buffer, size_t size) {
132 commitWrite();
133 if (!mStream->readFully(buffer, size)) {
134 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
135 << "Could not read back " << size << " bytes";
136 }
137 return size;
138 }
139
remainingWriteBufferSize() const140 size_t VulkanStream::remainingWriteBufferSize() const { return mWriteBuffer.size() - mWritePos; }
141
bufferedWrite(const void * buffer,size_t size)142 ssize_t VulkanStream::bufferedWrite(const void* buffer, size_t size) {
143 if (size > remainingWriteBufferSize()) {
144 mWriteBuffer.resize((mWritePos + size) << 1);
145 }
146 memcpy(mWriteBuffer.data() + mWritePos, buffer, size);
147 mWritePos += size;
148 return size;
149 }
150
write(const void * buffer,size_t size)151 ssize_t VulkanStream::write(const void* buffer, size_t size) { return bufferedWrite(buffer, size); }
152
commitWrite()153 void VulkanStream::commitWrite() {
154 if (!valid()) {
155 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
156 << "Tried to commit write to vulkan pipe with invalid pipe!";
157 }
158
159 int written = mStream->writeFully(mWriteBuffer.data(), mWritePos);
160
161 if (written) {
162 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
163 << "Did not write exactly " << mWritePos << " bytes!";
164 }
165 mWritePos = 0;
166 }
167
clearPool()168 void VulkanStream::clearPool() { mPool.freeAll(); }
169
setHandleMapping(VulkanHandleMapping * mapping)170 void VulkanStream::setHandleMapping(VulkanHandleMapping* mapping) {
171 mCurrentHandleMapping = mapping;
172 }
173
unsetHandleMapping()174 void VulkanStream::unsetHandleMapping() { mCurrentHandleMapping = &mDefaultHandleMapping; }
175
handleMapping() const176 VulkanHandleMapping* VulkanStream::handleMapping() const { return mCurrentHandleMapping; }
177
getFeatureBits() const178 uint32_t VulkanStream::getFeatureBits() const { return mFeatureBits; }
179
pool()180 android::base::BumpPool* VulkanStream::pool() { return &mPool; }
181
VulkanMemReadingStream(uint8_t * start,const gfxstream::host::FeatureSet & features)182 VulkanMemReadingStream::VulkanMemReadingStream(uint8_t* start, const gfxstream::host::FeatureSet& features)
183 : VulkanStream(nullptr, features), mStart(start) {}
184
~VulkanMemReadingStream()185 VulkanMemReadingStream::~VulkanMemReadingStream() {}
186
setBuf(uint8_t * buf)187 void VulkanMemReadingStream::setBuf(uint8_t* buf) {
188 mStart = buf;
189 mReadPos = 0;
190 resetTrace();
191 }
192
getBuf()193 uint8_t* VulkanMemReadingStream::getBuf() { return mStart; }
194
setReadPos(uintptr_t pos)195 void VulkanMemReadingStream::setReadPos(uintptr_t pos) { mReadPos = pos; }
196
read(void * buffer,size_t size)197 ssize_t VulkanMemReadingStream::read(void* buffer, size_t size) {
198 memcpy(buffer, mStart + mReadPos, size);
199 mReadPos += size;
200 return size;
201 }
202
write(const void * buffer,size_t size)203 ssize_t VulkanMemReadingStream::write(const void* buffer, size_t size) {
204 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
205 << "VulkanMemReadingStream does not support writing";
206 }
207
beginTrace()208 uint8_t* VulkanMemReadingStream::beginTrace() {
209 resetTrace();
210 return mTraceStart;
211 }
212
endTrace()213 size_t VulkanMemReadingStream::endTrace() {
214 uintptr_t current = (uintptr_t)(mStart + mReadPos);
215 size_t res = (size_t)(current - (uintptr_t)mTraceStart);
216 return res;
217 }
218
resetTrace()219 void VulkanMemReadingStream::resetTrace() { mTraceStart = mStart + mReadPos; }
220
221 } // namespace vk
222 } // namespace gfxstream
223