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