xref: /aosp_15_r20/external/swiftshader/src/Device/VertexProcessor.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 	const vk::VertexInputInterfaceState &vertexInputInterfaceState = pipelineState.getVertexInputInterfaceState();
71 	const vk::PreRasterizationState &preRasterizationState = pipelineState.getPreRasterizationState();
72 
73 	State state;
74 
75 	state.shaderID = vertexShader->getIdentifier();
76 	state.pipelineLayoutIdentifier = preRasterizationState.getPipelineLayout()->identifier;
77 	state.robustBufferAccess = vertexShader->getRobustBufferAccess();
78 	state.isPoint = vertexInputInterfaceState.getTopology() == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
79 	state.depthClipEnable = preRasterizationState.getDepthClipEnable();
80 	state.depthClipNegativeOneToOne = preRasterizationState.getDepthClipNegativeOneToOne();
81 
82 	for(size_t i = 0; i < MAX_INTERFACE_COMPONENTS / 4; i++)
83 	{
84 		state.input[i].format = inputs.getStream(i).format;
85 		// TODO: get rid of attribType -- just keep the VK format all the way through, this fully determines
86 		// how to handle the attribute.
87 		state.input[i].attribType = vertexShader->inputs[i * 4].Type;
88 	}
89 
90 	state.hash = state.computeHash();
91 
92 	return state;
93 }
94 
routine(const State & state,const vk::PipelineLayout * pipelineLayout,const SpirvShader * vertexShader,const vk::DescriptorSet::Bindings & descriptorSets)95 VertexProcessor::RoutineType VertexProcessor::routine(const State &state,
96                                                       const vk::PipelineLayout *pipelineLayout,
97                                                       const SpirvShader *vertexShader,
98                                                       const vk::DescriptorSet::Bindings &descriptorSets)
99 {
100 	auto routine = routineCache->lookup(state);
101 
102 	if(!routine)  // Create one
103 	{
104 		VertexRoutine *generator = new VertexProgram(state, pipelineLayout, vertexShader, descriptorSets);
105 		generator->generate();
106 		routine = (*generator)("VertexRoutine_%0.8X", state.shaderID);
107 		delete generator;
108 
109 		routineCache->add(state, routine);
110 	}
111 
112 	return routine;
113 }
114 
115 }  // namespace sw
116