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 #define E(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
29 
30 using emugl::ABORT_REASON_OTHER;
31 using emugl::FatalError;
32 
VulkanStream(IOStream * stream,const gfxstream::host::FeatureSet & features)33 VulkanStream::VulkanStream(IOStream* stream, const gfxstream::host::FeatureSet& features) : mStream(stream) {
34     unsetHandleMapping();
35 
36     if (features.VulkanNullOptionalStrings.enabled) {
37         mFeatureBits |= VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT;
38     }
39     if (features.VulkanIgnoredHandles.enabled) {
40         mFeatureBits |= VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT;
41     }
42     if (features.VulkanShaderFloat16Int8.enabled) {
43         mFeatureBits |= VULKAN_STREAM_FEATURE_SHADER_FLOAT16_INT8_BIT;
44     }
45 }
46 
47 VulkanStream::~VulkanStream() = default;
48 
setStream(IOStream * stream)49 void VulkanStream::setStream(IOStream* stream) { mStream = stream; }
50 
valid()51 bool VulkanStream::valid() { return true; }
52 
alloc(void ** ptrAddr,size_t bytes)53 void VulkanStream::alloc(void** ptrAddr, size_t bytes) {
54     if (!bytes) {
55         *ptrAddr = nullptr;
56         return;
57     }
58 
59     *ptrAddr = mPool.alloc(bytes);
60 
61     if (!*ptrAddr) {
62         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "alloc failed. Wanted size: " << bytes;
63     }
64 }
65 
loadStringInPlace(char ** forOutput)66 void VulkanStream::loadStringInPlace(char** forOutput) {
67     size_t len = getBe32();
68 
69     alloc((void**)forOutput, len + 1);
70 
71     memset(*forOutput, 0x0, len + 1);
72 
73     if (len > 0) read(*forOutput, len);
74 }
75 
loadStringArrayInPlace(char *** forOutput)76 void VulkanStream::loadStringArrayInPlace(char*** forOutput) {
77     size_t count = getBe32();
78 
79     if (!count) {
80         *forOutput = nullptr;
81         return;
82     }
83 
84     alloc((void**)forOutput, count * sizeof(char*));
85 
86     char** stringsForOutput = *forOutput;
87 
88     for (size_t i = 0; i < count; i++) {
89         loadStringInPlace(stringsForOutput + i);
90     }
91 }
92 
loadStringInPlaceWithStreamPtr(char ** forOutput,uint8_t ** streamPtr)93 void VulkanStream::loadStringInPlaceWithStreamPtr(char** forOutput, uint8_t** streamPtr) {
94     uint32_t len;
95     memcpy(&len, *streamPtr, sizeof(uint32_t));
96     *streamPtr += sizeof(uint32_t);
97     android::base::Stream::fromBe32((uint8_t*)&len);
98 
99     if (len == UINT32_MAX) {
100         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
101             << "VulkanStream can't allocate UINT32_MAX bytes";
102     }
103 
104     alloc((void**)forOutput, len + 1);
105 
106     if (len > 0) {
107         memcpy(*forOutput, *streamPtr, len);
108         *streamPtr += len;
109     }
110     (*forOutput)[len] = 0;
111 }
112 
loadStringArrayInPlaceWithStreamPtr(char *** forOutput,uint8_t ** streamPtr)113 void VulkanStream::loadStringArrayInPlaceWithStreamPtr(char*** forOutput, uint8_t** streamPtr) {
114     uint32_t count;
115     memcpy(&count, *streamPtr, sizeof(uint32_t));
116     *streamPtr += sizeof(uint32_t);
117     android::base::Stream::fromBe32((uint8_t*)&count);
118 
119     if (!count) {
120         *forOutput = nullptr;
121         return;
122     }
123 
124     alloc((void**)forOutput, count * sizeof(char*));
125 
126     char** stringsForOutput = *forOutput;
127 
128     for (size_t i = 0; i < count; i++) {
129         loadStringInPlaceWithStreamPtr(stringsForOutput + i, streamPtr);
130     }
131 }
132 
read(void * buffer,size_t size)133 ssize_t VulkanStream::read(void* buffer, size_t size) {
134     commitWrite();
135     if (!mStream->readFully(buffer, size)) {
136         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
137             << "Could not read back " << size << " bytes";
138     }
139     return size;
140 }
141 
remainingWriteBufferSize() const142 size_t VulkanStream::remainingWriteBufferSize() const { return mWriteBuffer.size() - mWritePos; }
143 
bufferedWrite(const void * buffer,size_t size)144 ssize_t VulkanStream::bufferedWrite(const void* buffer, size_t size) {
145     if (size > remainingWriteBufferSize()) {
146         mWriteBuffer.resize((mWritePos + size) << 1);
147     }
148     memcpy(mWriteBuffer.data() + mWritePos, buffer, size);
149     mWritePos += size;
150     return size;
151 }
152 
write(const void * buffer,size_t size)153 ssize_t VulkanStream::write(const void* buffer, size_t size) { return bufferedWrite(buffer, size); }
154 
commitWrite()155 void VulkanStream::commitWrite() {
156     if (!valid()) {
157         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
158             << "Tried to commit write to vulkan pipe with invalid pipe!";
159     }
160 
161     int written = mStream->writeFully(mWriteBuffer.data(), mWritePos);
162 
163     if (written) {
164         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
165             << "Did not write exactly " << mWritePos << " bytes!";
166     }
167     mWritePos = 0;
168 }
169 
clearPool()170 void VulkanStream::clearPool() { mPool.freeAll(); }
171 
setHandleMapping(VulkanHandleMapping * mapping)172 void VulkanStream::setHandleMapping(VulkanHandleMapping* mapping) {
173     mCurrentHandleMapping = mapping;
174 }
175 
unsetHandleMapping()176 void VulkanStream::unsetHandleMapping() { mCurrentHandleMapping = &mDefaultHandleMapping; }
177 
handleMapping() const178 VulkanHandleMapping* VulkanStream::handleMapping() const { return mCurrentHandleMapping; }
179 
getFeatureBits() const180 uint32_t VulkanStream::getFeatureBits() const { return mFeatureBits; }
181 
pool()182 android::base::BumpPool* VulkanStream::pool() { return &mPool; }
183 
VulkanMemReadingStream(uint8_t * start,const gfxstream::host::FeatureSet & features)184 VulkanMemReadingStream::VulkanMemReadingStream(uint8_t* start, const gfxstream::host::FeatureSet& features)
185     : VulkanStream(nullptr, features), mStart(start) {}
186 
~VulkanMemReadingStream()187 VulkanMemReadingStream::~VulkanMemReadingStream() {}
188 
setBuf(uint8_t * buf)189 void VulkanMemReadingStream::setBuf(uint8_t* buf) {
190     mStart = buf;
191     mReadPos = 0;
192     resetTrace();
193 }
194 
getBuf()195 uint8_t* VulkanMemReadingStream::getBuf() { return mStart; }
196 
setReadPos(uintptr_t pos)197 void VulkanMemReadingStream::setReadPos(uintptr_t pos) { mReadPos = pos; }
198 
read(void * buffer,size_t size)199 ssize_t VulkanMemReadingStream::read(void* buffer, size_t size) {
200     memcpy(buffer, mStart + mReadPos, size);
201     mReadPos += size;
202     return size;
203 }
204 
write(const void * buffer,size_t size)205 ssize_t VulkanMemReadingStream::write(const void* buffer, size_t size) {
206     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
207         << "VulkanMemReadingStream does not support writing";
208 }
209 
beginTrace()210 uint8_t* VulkanMemReadingStream::beginTrace() {
211     resetTrace();
212     return mTraceStart;
213 }
214 
endTrace()215 size_t VulkanMemReadingStream::endTrace() {
216     uintptr_t current = (uintptr_t)(mStart + mReadPos);
217     size_t res = (size_t)(current - (uintptr_t)mTraceStart);
218     return res;
219 }
220 
resetTrace()221 void VulkanMemReadingStream::resetTrace() { mTraceStart = mStart + mReadPos; }
222 
223 }  // namespace vk
224 }  // namespace gfxstream
225