Ejemplo n.º 1
0
    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;
    }
Ejemplo n.º 2
0
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;
}