• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "VertexProcessor.hpp"
16 
17 #include "Pipeline/Constants.hpp"
18 #include "Pipeline/VertexProgram.hpp"
19 #include "System/Debug.hpp"
20 #include "System/Math.hpp"
21 #include "Vulkan/VkPipelineLayout.hpp"
22 
23 #include <cstring>
24 
25 namespace sw {
26 
clear()27 void VertexCache::clear()
28 {
29 	for(uint32_t i = 0; i < SIZE; i++)
30 	{
31 		tag[i] = 0xFFFFFFFF;
32 	}
33 }
34 
computeHash()35 uint32_t VertexProcessor::States::computeHash()
36 {
37 	uint32_t *state = reinterpret_cast<uint32_t *>(this);
38 	uint32_t hash = 0;
39 
40 	for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
41 	{
42 		hash ^= state[i];
43 	}
44 
45 	return hash;
46 }
47 
operator ==(const State & state) const48 bool VertexProcessor::State::operator==(const State &state) const
49 {
50 	if(hash != state.hash)
51 	{
52 		return false;
53 	}
54 
55 	return *static_cast<const States *>(this) == static_cast<const States &>(state);
56 }
57 
VertexProcessor()58 VertexProcessor::VertexProcessor()
59 {
60 	setRoutineCacheSize(1024);
61 }
62 
setRoutineCacheSize(int cacheSize)63 void VertexProcessor::setRoutineCacheSize(int cacheSize)
64 {
65 	routineCache = std::make_unique<RoutineCacheType>(clamp(cacheSize, 1, 65536));
66 }
67 
update(const vk::GraphicsState & pipelineState,const sw::SpirvShader * vertexShader,const vk::Inputs & inputs)68 const VertexProcessor::State VertexProcessor::update(const vk::GraphicsState &pipelineState, const sw::SpirvShader *vertexShader, const vk::Inputs &inputs)
69 {
70 	State state;
71 
72 	state.shaderID = vertexShader->getSerialID();
73 	state.pipelineLayoutIdentifier = pipelineState.getPipelineLayout()->identifier;
74 	state.robustBufferAccess = pipelineState.getRobustBufferAccess();
75 	state.isPoint = pipelineState.getTopology() == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
76 
77 	for(size_t i = 0; i < MAX_INTERFACE_COMPONENTS / 4; i++)
78 	{
79 		state.input[i].format = inputs.getStream(i).format;
80 		// TODO: get rid of attribType -- just keep the VK format all the way through, this fully determines
81 		// how to handle the attribute.
82 		state.input[i].attribType = vertexShader->inputs[i * 4].Type;
83 	}
84 
85 	state.hash = state.computeHash();
86 
87 	return state;
88 }
89 
routine(const State & state,vk::PipelineLayout const * pipelineLayout,SpirvShader const * vertexShader,const vk::DescriptorSet::Bindings & descriptorSets)90 VertexProcessor::RoutineType VertexProcessor::routine(const State &state,
91                                                       vk::PipelineLayout const *pipelineLayout,
92                                                       SpirvShader const *vertexShader,
93                                                       const vk::DescriptorSet::Bindings &descriptorSets)
94 {
95 	auto routine = routineCache->lookup(state);
96 
97 	if(!routine)  // Create one
98 	{
99 		VertexRoutine *generator = new VertexProgram(state, pipelineLayout, vertexShader, descriptorSets);
100 		generator->generate();
101 		routine = (*generator)("VertexRoutine_%0.8X", state.shaderID);
102 		delete generator;
103 
104 		routineCache->add(state, routine);
105 	}
106 
107 	return routine;
108 }
109 
110 }  // namespace sw
111