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