uint32_t DirectXInputLayoutRegistry::create(const Vertices& vertices) { TB::runtimeCheck(vertices.size() > 0); const char* semantics[] = { "POSITION", "NORMAL", "TEXCOORD", "COLOR" }; const DXGI_FORMAT formats[] = { DXGI_FORMAT(0), DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT }; // Input layout elements std::vector<D3D11_INPUT_ELEMENT_DESC> elements; for (size_t i = 0; i < vertices.size(); i++) { const auto& stream = vertices[i]; elements.push_back({ semantics[(int)stream.semantic], (UINT)stream.usageIndex, formats[stream.elements], (UINT)i, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); } // Hash the memory bytes of the element uint32_t id = hash(reinterpret_cast<uint8_t*>(&elements[0]), elements.size() * sizeof(D3D11_INPUT_ELEMENT_DESC)); auto item = mRegistry.find(id); if (item == mRegistry.end()) { std::stringstream fakeVSCode; const char* memberTypes[] = { nullptr, "float", "float2", "float3", "float4" }; // Create a fake vertex shader for the input layout fakeVSCode << "struct VSInput"; fakeVSCode << "{"; for (size_t i = 0; i < vertices.size(); i++) { const auto& stream = vertices[i]; fakeVSCode << memberTypes[stream.elements] << " _" << i << " : " << semantics[(int)stream.semantic] << stream.usageIndex << ";"; } fakeVSCode << "};"; fakeVSCode << "float4 MainVS(VSInput input) : SV_POSITION { return float4(0, 0, 0, 1); }"; DirectXShader fakeVS(mRenderer, DataChunk(fakeVSCode.str()), "MainVS", ShaderType::Vertex); ComPtr<ID3D11InputLayout> inputLayout; HRESULT hr = mRenderer->getDevice()->CreateInputLayout(&elements[0], (UINT)elements.size(), fakeVS.getBlob()->GetBufferPointer(), fakeVS.getBlob()->GetBufferSize(), inputLayout.getInitRef()); TB::runtimeCheck(hr == S_OK); mRegistry.emplace(id, inputLayout); } return id; }
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Data layout: // // byte: boolean states // { // byte: stream type // byte: stream count and normalized // } [MAX_VERTEX_INPUTS] // { // byte[32]: reserved sampler state // } [VERTEX_TEXTURE_IMAGE_UNITS] // // char source[] // null terminated const size_t kHeaderSize = 1 + 2 * sw::MAX_VERTEX_INPUTS + 32 * sw::VERTEX_TEXTURE_IMAGE_UNITS; if(size <= kHeaderSize) { return 0; } if(data[size - 1] != 0) { return 0; } std::unique_ptr<ScopedPoolAllocatorAndTLS> allocatorAndTLS(new ScopedPoolAllocatorAndTLS); std::unique_ptr<sw::VertexShader> shader(new sw::VertexShader); std::unique_ptr<FakeVS> fakeVS(new FakeVS(shader.get())); std::unique_ptr<TranslatorASM> glslCompiler(new TranslatorASM(fakeVS.get(), GL_VERTEX_SHADER)); // TODO([email protected]): have a function to init to default values somewhere ShBuiltInResources resources; resources.MaxVertexAttribs = sw::MAX_VERTEX_INPUTS; resources.MaxVertexUniformVectors = sw::VERTEX_UNIFORM_VECTORS - 3; resources.MaxVaryingVectors = MIN(sw::MAX_VERTEX_OUTPUTS, sw::MAX_VERTEX_INPUTS); resources.MaxVertexTextureImageUnits = sw::VERTEX_TEXTURE_IMAGE_UNITS; resources.MaxCombinedTextureImageUnits = sw::TEXTURE_IMAGE_UNITS + sw::VERTEX_TEXTURE_IMAGE_UNITS; resources.MaxTextureImageUnits = sw::TEXTURE_IMAGE_UNITS; resources.MaxFragmentUniformVectors = sw::FRAGMENT_UNIFORM_VECTORS - 3; resources.MaxDrawBuffers = sw::RENDERTARGETS; resources.MaxVertexOutputVectors = 16; // ??? resources.MaxFragmentInputVectors = 15; // ??? resources.MinProgramTexelOffset = sw::MIN_PROGRAM_TEXEL_OFFSET; resources.MaxProgramTexelOffset = sw::MAX_PROGRAM_TEXEL_OFFSET; resources.OES_standard_derivatives = 1; resources.OES_fragment_precision_high = 1; resources.OES_EGL_image_external = 1; resources.OES_EGL_image_external_essl3 = 1; resources.EXT_draw_buffers = 1; resources.ARB_texture_rectangle = 1; resources.MaxCallStackDepth = 16; glslCompiler->Init(resources); const char* glslSource = reinterpret_cast<const char*>(data + kHeaderSize); if (!glslCompiler->compile(&glslSource, 1, SH_OBJECT_CODE)) { return 0; } std::unique_ptr<sw::VertexShader> bytecodeShader(new sw::VertexShader(fakeVS->getVertexShader())); sw::VertexProcessor::State state; state.textureSampling = bytecodeShader->containsTextureSampling(); state.positionRegister = bytecodeShader->getPositionRegister(); state.pointSizeRegister = bytecodeShader->getPointSizeRegister(); state.preTransformed = (data[0] & 0x01) != 0; state.superSampling = (data[0] & 0x02) != 0; state.transformFeedbackQueryEnabled = (data[0] & 0x08) != 0; state.transformFeedbackEnabled = (data[0] & 0x10) != 0; state.verticesPerPrimitive = 1 + ((data[0] & 0x20) != 0) + ((data[0] & 0x40) != 0); if((data[0] & 0x80) != 0) // Unused/reserved. { return 0; } constexpr int MAX_ATTRIBUTE_COMPONENTS = 4; struct Stream { uint8_t count : BITS(MAX_ATTRIBUTE_COMPONENTS); bool normalized : 1; uint8_t reserved : 8 - BITS(MAX_ATTRIBUTE_COMPONENTS) - 1; }; for(int i = 0; i < sw::MAX_VERTEX_INPUTS; i++) { sw::StreamType type = (sw::StreamType)data[1 + 2 * i + 0]; Stream stream = (Stream&)data[1 + 2 * i + 1]; if(type > sw::STREAMTYPE_LAST) return 0; if(stream.count > MAX_ATTRIBUTE_COMPONENTS) return 0; if(stream.reserved != 0) return 0; state.input[i].type = type; state.input[i].count = stream.count; state.input[i].normalized = stream.normalized; state.input[i].attribType = bytecodeShader->getAttribType(i); } for(unsigned int i = 0; i < sw::VERTEX_TEXTURE_IMAGE_UNITS; i++) { // TODO // if(bytecodeShader->usesSampler(i)) // { // state.samplerState[i] = context->sampler[sw::TEXTURE_IMAGE_UNITS + i].samplerState(); // } for(int j = 0; j < 32; j++) { if(data[1 + 2 * sw::MAX_VERTEX_INPUTS + 32 * i + j] != 0) { return 0; } } } for(int i = 0; i < sw::MAX_VERTEX_OUTPUTS; i++) { state.output[i].xWrite = bytecodeShader->getOutput(i, 0).active(); state.output[i].yWrite = bytecodeShader->getOutput(i, 1).active(); state.output[i].zWrite = bytecodeShader->getOutput(i, 2).active(); state.output[i].wWrite = bytecodeShader->getOutput(i, 3).active(); } sw::VertexProgram program(state, bytecodeShader.get()); program.generate(); sw::Routine *routine = program("VertexRoutine"); assert(routine); const void *entry = routine->getEntry(); assert(entry); (void)entry; delete routine; return 0; }