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