1// Copyright 2017 The SwiftShader Authors. All Rights Reserved. 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 15#include "OpenGL/compiler/InitializeGlobals.h" 16#include "OpenGL/compiler/InitializeParseContext.h" 17#include "OpenGL/compiler/TranslatorASM.h" 18 19// TODO: Debug macros of the GLSL compiler clash with core SwiftShader's. 20// They should not be exposed through the interface headers above. 21#undef ASSERT 22#undef UNIMPLEMENTED 23 24#include "Renderer/VertexProcessor.hpp" 25#include "Shader/VertexProgram.hpp" 26 27#include <cstdint> 28#include <memory> 29#include <cassert> 30 31namespace { 32 33// TODO(cwallez@google.com): Like in ANGLE, disable most of the pool allocator for fuzzing 34// This is a helper class to make sure all the resources used by the compiler are initialized 35class ScopedPoolAllocatorAndTLS { 36 public: 37 ScopedPoolAllocatorAndTLS() { 38 InitializeParseContextIndex(); 39 InitializePoolIndex(); 40 SetGlobalPoolAllocator(&allocator); 41 } 42 ~ScopedPoolAllocatorAndTLS() { 43 SetGlobalPoolAllocator(nullptr); 44 FreePoolIndex(); 45 FreeParseContextIndex(); 46 } 47 48 private: 49 TPoolAllocator allocator; 50}; 51 52// Trivial implementation of the glsl::Shader interface that fakes being an API-level 53// shader object. 54class FakeVS : public glsl::Shader { 55 public: 56 FakeVS(sw::VertexShader* bytecode) : bytecode(bytecode) { 57 } 58 59 sw::Shader *getShader() const override { 60 return bytecode; 61 } 62 sw::VertexShader *getVertexShader() const override { 63 return bytecode; 64 } 65 66 private: 67 sw::VertexShader* bytecode; 68}; 69 70} // anonymous namespace 71 72extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) 73{ 74 // Data layout: 75 // 76 // byte: boolean states 77 // { 78 // byte: stream type 79 // byte: stream count and normalized 80 // } [MAX_VERTEX_INPUTS] 81 // { 82 // byte[32]: reserved sampler state 83 // } [VERTEX_TEXTURE_IMAGE_UNITS] 84 // 85 // char source[] // null terminated 86 const size_t kHeaderSize = 1 + 2 * sw::MAX_VERTEX_INPUTS + 32 * sw::VERTEX_TEXTURE_IMAGE_UNITS; 87 88 if(size <= kHeaderSize) 89 { 90 return 0; 91 } 92 93 if (data[size -1] != 0) 94 { 95 return 0; 96 } 97 98 std::unique_ptr<ScopedPoolAllocatorAndTLS> allocatorAndTLS(new ScopedPoolAllocatorAndTLS); 99 std::unique_ptr<sw::VertexShader> shader(new sw::VertexShader); 100 std::unique_ptr<FakeVS> fakeVS(new FakeVS(shader.get())); 101 102 std::unique_ptr<TranslatorASM> glslCompiler(new TranslatorASM(fakeVS.get(), GL_VERTEX_SHADER)); 103 104 // TODO(cwallez@google.com): have a function to init to default values somewhere 105 ShBuiltInResources resources; 106 resources.MaxVertexAttribs = sw::MAX_VERTEX_INPUTS; 107 resources.MaxVertexUniformVectors = sw::VERTEX_UNIFORM_VECTORS - 3; 108 resources.MaxVaryingVectors = MIN(sw::MAX_VERTEX_OUTPUTS, sw::MAX_VERTEX_INPUTS); 109 resources.MaxVertexTextureImageUnits = sw::VERTEX_TEXTURE_IMAGE_UNITS; 110 resources.MaxCombinedTextureImageUnits = sw::TEXTURE_IMAGE_UNITS + sw::VERTEX_TEXTURE_IMAGE_UNITS; 111 resources.MaxTextureImageUnits = sw::TEXTURE_IMAGE_UNITS; 112 resources.MaxFragmentUniformVectors = sw::FRAGMENT_UNIFORM_VECTORS - 3; 113 resources.MaxDrawBuffers = sw::RENDERTARGETS; 114 resources.MaxVertexOutputVectors = 16; // ??? 115 resources.MaxFragmentInputVectors = 15; // ??? 116 resources.MinProgramTexelOffset = sw::MIN_PROGRAM_TEXEL_OFFSET; 117 resources.MaxProgramTexelOffset = sw::MAX_PROGRAM_TEXEL_OFFSET; 118 resources.OES_standard_derivatives = 1; 119 resources.OES_fragment_precision_high = 1; 120 resources.OES_EGL_image_external = 1; 121 resources.EXT_draw_buffers = 1; 122 resources.ARB_texture_rectangle = 1; 123 resources.MaxCallStackDepth = 16; 124 125 glslCompiler->Init(resources); 126 127 const char* glslSource = reinterpret_cast<const char*>(data + kHeaderSize); 128 if (!glslCompiler->compile(&glslSource, 1, SH_OBJECT_CODE)) 129 { 130 return 0; 131 } 132 133 std::unique_ptr<sw::VertexShader> bytecodeShader(new sw::VertexShader(fakeVS->getVertexShader())); 134 135 sw::VertexProcessor::State state; 136 137 state.textureSampling = bytecodeShader->containsTextureSampling(); 138 state.positionRegister = bytecodeShader->getPositionRegister(); 139 state.pointSizeRegister = bytecodeShader->getPointSizeRegister(); 140 141 state.preTransformed = (data[0] & 0x01) != 0; 142 state.superSampling = (data[0] & 0x02) != 0; 143 state.multiSampling = (data[0] & 0x04) != 0; 144 145 state.transformFeedbackQueryEnabled = (data[0] & 0x08) != 0; 146 state.transformFeedbackEnabled = (data[0] & 0x10) != 0; 147 state.verticesPerPrimitive = 1 + ((data[0] & 0x20) != 0) + ((data[0] & 0x40) != 0); 148 149 if((data[0] & 0x80) != 0) // Unused/reserved. 150 { 151 return 0; 152 } 153 154 constexpr int MAX_ATTRIBUTE_COMPONENTS = 4; 155 156 struct Stream 157 { 158 uint8_t count : BITS(MAX_ATTRIBUTE_COMPONENTS); 159 bool normalized : 1; 160 uint8_t reserved : 8 - BITS(MAX_ATTRIBUTE_COMPONENTS) - 1; 161 }; 162 163 for(int i = 0; i < sw::MAX_VERTEX_INPUTS; i++) 164 { 165 sw::StreamType type = (sw::StreamType)data[1 + 2 * i + 0]; 166 Stream stream = (Stream&)data[1 + 2 * i + 1]; 167 168 if(type > sw::STREAMTYPE_LAST) return 0; 169 if(stream.count > MAX_ATTRIBUTE_COMPONENTS) return 0; 170 if(stream.reserved != 0) return 0; 171 172 state.input[i].type = type; 173 state.input[i].count = stream.count; 174 state.input[i].normalized = stream.normalized; 175 state.input[i].attribType = bytecodeShader->getAttribType(i); 176 } 177 178 for(unsigned int i = 0; i < sw::VERTEX_TEXTURE_IMAGE_UNITS; i++) 179 { 180 // TODO 181 // if(bytecodeShader->usesSampler(i)) 182 // { 183 // state.samplerState[i] = context->sampler[sw::TEXTURE_IMAGE_UNITS + i].samplerState(); 184 // } 185 186 for(int j = 0; j < 32; j++) 187 { 188 if(data[1 + 2 * sw::MAX_VERTEX_INPUTS + 32 * i + j] != 0) 189 { 190 return 0; 191 } 192 } 193 } 194 195 for(int i = 0; i < sw::MAX_VERTEX_OUTPUTS; i++) 196 { 197 state.output[i].xWrite = bytecodeShader->getOutput(i, 0).active(); 198 state.output[i].yWrite = bytecodeShader->getOutput(i, 1).active(); 199 state.output[i].zWrite = bytecodeShader->getOutput(i, 2).active(); 200 state.output[i].wWrite = bytecodeShader->getOutput(i, 3).active(); 201 } 202 203 sw::VertexProgram program(state, bytecodeShader.get()); 204 program.generate(); 205 206 sw::Routine *routine = program(L"VertexRoutine"); 207 assert(routine); 208 const void *entry = routine->getEntry(); 209 assert(entry); (void)entry; 210 delete routine; 211 212 return 0; 213} 214