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