File src/image_main.cpp added (mode: 100644) (index 0000000..2bac796) |
|
1 |
|
#include <jen/framework.h> |
|
2 |
|
#include <mesh/cube.h> |
|
3 |
|
|
|
4 |
|
struct ComputeBindings { |
|
5 |
|
[[nodiscard]] jen::vk::Result |
|
6 |
|
init(jen::vk::ModuleCompute *p_mc, math::v3u32 extent) |
|
7 |
|
{ |
|
8 |
|
jl::array<jen::vk::ImageCreateInfo, 2> images_info; |
|
9 |
|
|
|
10 |
|
auto &src_image = images_info[0]; { |
|
11 |
|
src_image.extent = extent; |
|
12 |
|
src_image.layer_count = 1; |
|
13 |
|
src_image.mip_level_count = 1; |
|
14 |
|
src_image.format = VK_FORMAT_R8G8B8A8_UINT; |
|
15 |
|
src_image.type = vkw::ImType::_2D; |
|
16 |
|
src_image.samples = 1; |
|
17 |
|
src_image.usage = jen::vk::ImageUseFlag::TRANSFER_DST |
|
18 |
|
| jen::vk::ImageUseFlag::STORAGE; |
|
19 |
|
} |
|
20 |
|
auto &dst_image = images_info[1]; { |
|
21 |
|
dst_image = src_image; |
|
22 |
|
dst_image.usage = jen::vk::ImageUseFlag::STORAGE |
|
23 |
|
| jen::vk::ImageUseFlag::TRANSFER_SRC; |
|
24 |
|
} |
|
25 |
|
|
|
26 |
|
auto res = p_mc->create_images(images_info, images.begin()); |
|
27 |
|
if (res != VK_SUCCESS) |
|
28 |
|
return res; |
|
29 |
|
|
|
30 |
|
bindings[0].init(&images[0], 0); |
|
31 |
|
bindings[1].init(&images[1], 1); |
|
32 |
|
binds = {}; |
|
33 |
|
binds.storage_image = bindings; |
|
34 |
|
|
|
35 |
|
this->extent = extent; |
|
36 |
|
|
|
37 |
|
return VK_SUCCESS; |
|
38 |
|
} |
|
39 |
|
void destroy(jen::vk::ModuleCompute *p_mc) { |
|
40 |
|
p_mc->destroy_images(images.begin(), images.count32()); |
|
41 |
|
} |
|
42 |
|
|
|
43 |
|
jl::array<jen::vk::Image, 2> images; |
|
44 |
|
jl::array<jen::vk::BindingImage, 2> bindings; |
|
45 |
|
math::v3u32 extent; |
|
46 |
|
jen::vk::Bindings binds; |
|
47 |
|
}; |
|
48 |
|
|
|
49 |
|
struct Color { |
|
50 |
|
uint8_t r,g,b,a; |
|
51 |
|
}; |
|
52 |
|
|
|
53 |
|
enum ShaderType { |
|
54 |
|
NONE, CLEAR, WHITE_NOISE |
|
55 |
|
}; |
|
56 |
|
|
|
57 |
|
void |
|
58 |
|
compute(ShaderType type, ComputeBindings *p_binds, jen::vk::ModuleCompute *p_mc, |
|
59 |
|
Color *p_src, Color *p_dst, jl::time *p_compute_elapsed) |
|
60 |
|
{ |
|
61 |
|
vkw::ShaderConstant type_const; |
|
62 |
|
type_const.id = 0; |
|
63 |
|
type_const.size = 4; |
|
64 |
|
type_const.offset = 0; |
|
65 |
|
|
|
66 |
|
uint32_t consts = type; |
|
67 |
|
vkw::ShaderSpecialization spec; |
|
68 |
|
spec.p_data = &consts; |
|
69 |
|
spec.data_size = type_const.size; |
|
70 |
|
spec.constants.count = 1; |
|
71 |
|
spec.constants.p = &type_const; |
|
72 |
|
|
|
73 |
|
jen::vk::ComputePipeline pipeline; |
|
74 |
|
|
|
75 |
|
jen::vk::Result res; |
|
76 |
|
res = p_mc->create_pipeline(p_binds->binds, "image.spv", &spec, &pipeline); |
|
77 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
78 |
|
|
|
79 |
|
jen::vk::BindingsSet set; |
|
80 |
|
res = p_mc->create_bindingSet(pipeline, p_binds->binds, &set); |
|
81 |
|
|
|
82 |
|
jen::vk::ComputeCmdUnit *p_unit; |
|
83 |
|
res = p_mc->create_cmdUnit(&p_unit); |
|
84 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
85 |
|
|
|
86 |
|
jen::vk::ImageTransfer write; |
|
87 |
|
write.mip_level = 0; |
|
88 |
|
write.layer_offset = 0; |
|
89 |
|
write.layer_count = 1; |
|
90 |
|
write.offset = {}; |
|
91 |
|
write.extent = p_binds->extent; |
|
92 |
|
write.p_data = p_src; |
|
93 |
|
|
|
94 |
|
jen::vk::ImageTransfer read; |
|
95 |
|
read = write; |
|
96 |
|
read.p_data = p_dst; |
|
97 |
|
|
|
98 |
|
jen::vk::ImageTransfers writes, reads; |
|
99 |
|
writes.p_image = &p_binds->images[0]; |
|
100 |
|
writes.transfers = write; |
|
101 |
|
reads.p_image = &p_binds->images[1]; |
|
102 |
|
reads.transfers = read; |
|
103 |
|
|
|
104 |
|
jen::vk::ComputeInfo info = {}; |
|
105 |
|
info.p_cmdUnit = p_unit; |
|
106 |
|
info.p_pipeline = &pipeline; |
|
107 |
|
info.p_bindingsSet = &set; |
|
108 |
|
info.p_bindings = &p_binds->binds; |
|
109 |
|
info.group_count = {p_binds->extent.x, p_binds->extent.y, p_binds->extent.z}; |
|
110 |
|
info.images_writes = writes; |
|
111 |
|
info.images_reads = reads; |
|
112 |
|
|
|
113 |
|
auto start = jl::time::current(); |
|
114 |
|
{ |
|
115 |
|
res = p_mc->compute(info); |
|
116 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
117 |
|
res = p_mc->read(p_unit, info.buffer_reads, info.images_reads); |
|
118 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
119 |
|
} |
|
120 |
|
*p_compute_elapsed = start.elapsed(jl::time::current()); |
|
121 |
|
|
|
122 |
|
p_mc->destroy_cmdUnit(p_unit); |
|
123 |
|
p_mc->destroy_bindingSet(&set); |
|
124 |
|
p_mc->destroy_pipeline(&pipeline); |
|
125 |
|
} |
|
126 |
|
|
|
127 |
|
struct RenderImage { |
|
128 |
|
[[nodiscard]] jen::vk::Result |
|
129 |
|
init_texture(jen::vk::ModuleGraphics *p_mg, math::v3u32 extent, void *p_data) |
|
130 |
|
{ |
|
131 |
|
// data must exist until texture will be prepared in separate thread |
|
132 |
|
// GpuTexture.state LOADING -> DONE |
|
133 |
|
// So "static" keyword is added here, this function called only once anyway |
|
134 |
|
static jrf::Image im; |
|
135 |
|
im.format = jrf::Image::Format::R8G8B8A8_SRGB; |
|
136 |
|
im.extent = {uint16_t(extent.x), uint16_t(extent.y), uint16_t(extent.z), 4}; |
|
137 |
|
im.size = vkw::format_size(VkFormat(im.format)); |
|
138 |
|
im.p_pixels = p_data; |
|
139 |
|
|
|
140 |
|
model.tex.layer_index = 0; |
|
141 |
|
|
|
142 |
|
return p_mg->create(&im, &model.tex.p_data, false); |
|
143 |
|
} |
|
144 |
|
|
|
145 |
|
[[nodiscard]] jen::vk::Result |
|
146 |
|
init_mesh(jen::vk::ModuleGraphics *p_mg) |
|
147 |
|
{ |
|
148 |
|
struct Vertex { |
|
149 |
|
math::v3f pos; |
|
150 |
|
math::v2f tex; |
|
151 |
|
math::v3f nor; |
|
152 |
|
}; |
|
153 |
|
static_assert (sizeof(Vertex) == sizeof(math::vector<8, float>)); |
|
154 |
|
|
|
155 |
|
using Face = mesh::cube::Face; |
|
156 |
|
constexpr static const Vertex VERTICES[4] = { |
|
157 |
|
{{ 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f }, mesh::cube::NORMALS[Face::TOP] }, |
|
158 |
|
{{ 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f }, mesh::cube::NORMALS[Face::TOP] }, |
|
159 |
|
{{ 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f }, mesh::cube::NORMALS[Face::TOP] }, |
|
160 |
|
{{ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f }, mesh::cube::NORMALS[Face::TOP] } |
|
161 |
|
}; |
|
162 |
|
struct Mesh { |
|
163 |
|
jl::array<math::v3f, 4> positions = { |
|
164 |
|
VERTICES[0].pos, VERTICES[1].pos, VERTICES[2].pos, VERTICES[3].pos |
|
165 |
|
}; |
|
166 |
|
jl::array<math::v2f, 4> texture_coordinate = { |
|
167 |
|
VERTICES[0].tex, VERTICES[1].tex, VERTICES[2].tex, VERTICES[3].tex |
|
168 |
|
}; |
|
169 |
|
jl::array<math::v3f, 4> normals = { |
|
170 |
|
VERTICES[0].nor, VERTICES[1].nor, VERTICES[2].nor, VERTICES[3].nor |
|
171 |
|
}; |
|
172 |
|
uint16_t indices[6] = { 0, 1, 2, 2, 3, 0 }; |
|
173 |
|
}; |
|
174 |
|
|
|
175 |
|
constexpr static const Mesh MESH = {}; |
|
176 |
|
jen::vk::WriteData write_data; |
|
177 |
|
write_data.p = const_cast<Mesh*>(&MESH); |
|
178 |
|
write_data.size = sizeof(MESH); |
|
179 |
|
|
|
180 |
|
|
|
181 |
|
jen::vk::Result res = p_mg->create(write_data, &model.ver.p_data, false); |
|
182 |
|
|
|
183 |
|
model.ver.count = 4; |
|
184 |
|
model.ver.offsets = {}; |
|
185 |
|
model.ver.offsets[jen::vk::VAttr::POSITION] = 0; |
|
186 |
|
model.ver.offsets[jen::vk::VAttr::TEX_COORD] |
|
187 |
|
= offsetof(Mesh,texture_coordinate); |
|
188 |
|
model.ver.offsets[jen::vk::VAttr::NORMAL] |
|
189 |
|
= offsetof(Mesh,normals); |
|
190 |
|
|
|
191 |
|
model.ind.type = vkw::IndexType::U16; |
|
192 |
|
model.ind.count = 6; |
|
193 |
|
model.ind.offset = offsetof(Mesh, indices); |
|
194 |
|
model.ind.p_data = model.ver.p_data; |
|
195 |
|
|
|
196 |
|
model.shift = {}; |
|
197 |
|
model.shader_data.position = {-0.5,1,-0.5}; |
|
198 |
|
model.shader_data.transform = math::scale<4>(1.f); |
|
199 |
|
return res; |
|
200 |
|
} |
|
201 |
|
|
|
202 |
|
jen::vk::Model model; |
|
203 |
|
}; |
|
204 |
|
|
|
205 |
|
|
|
206 |
|
struct Program |
|
207 |
|
{ |
|
208 |
|
void run() { |
|
209 |
|
jassert_release(jl::allocate(&p_pixels), "allocation failed"); |
|
210 |
|
for (auto &d : p_pixels->data) { |
|
211 |
|
for (auto &c : d) { |
|
212 |
|
c.a = 255; |
|
213 |
|
c.r = 127; |
|
214 |
|
c.g = 127; |
|
215 |
|
c.b = 127; |
|
216 |
|
} |
|
217 |
|
} |
|
218 |
|
|
|
219 |
|
if (not fw.init(jen::ModulesFlag::COMPUTE | jen::ModulesFlag::GRAPHICS, |
|
220 |
|
"JEN image compute example")) |
|
221 |
|
jabort_release("framework start failed"); |
|
222 |
|
|
|
223 |
|
fw.settings.shaders.shading = |
|
224 |
|
jen::vk::ShaderOptions::Shading::NO_LIGHTING; |
|
225 |
|
(void)fw.graphics.apply_settings(fw.settings); |
|
226 |
|
|
|
227 |
|
jen::vk::Result res = binds.init(&fw.compute, EXTENT); |
|
228 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
229 |
|
|
|
230 |
|
shader_type = ShaderType::WHITE_NOISE; |
|
231 |
|
model.model.tex.p_data = nullptr; |
|
232 |
|
regenerate(); |
|
233 |
|
res = model.init_mesh(&fw.graphics); |
|
234 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
235 |
|
|
|
236 |
|
screen.init(fw.instance.window, {}, {0,1,0}, {0,0,1}); |
|
237 |
|
screen.frustum.zNear = 0.01f; |
|
238 |
|
screen.frustum.zFar = 10; |
|
239 |
|
|
|
240 |
|
bool drawn = false; |
|
241 |
|
loop.loop(&fw, [&drawn, this](){ |
|
242 |
|
auto &w = fw.instance.window; |
|
243 |
|
ShaderType new_st = shader_type; |
|
244 |
|
if (w.is_on(Key::k1)) |
|
245 |
|
new_st = ShaderType::NONE; |
|
246 |
|
if (w.is_on(Key::k2)) |
|
247 |
|
new_st = ShaderType::CLEAR; |
|
248 |
|
if (w.is_on(Key::k3)) |
|
249 |
|
new_st = ShaderType::WHITE_NOISE; |
|
250 |
|
|
|
251 |
|
loop.draw = w.is_damaged; |
|
252 |
|
if (not drawn) { |
|
253 |
|
if (model.model.tex.p_data->state == jen::vk::State::DONE |
|
254 |
|
and |
|
255 |
|
model.model.ver.p_data->state == jen::vk::State::DONE) { |
|
256 |
|
drawn = true; |
|
257 |
|
loop.draw = true; |
|
258 |
|
} |
|
259 |
|
} |
|
260 |
|
if (new_st != shader_type) { |
|
261 |
|
shader_type = new_st; |
|
262 |
|
regenerate(); |
|
263 |
|
drawn = false; |
|
264 |
|
} |
|
265 |
|
if (loop.draw) { |
|
266 |
|
screen.update(fw.instance.window); |
|
267 |
|
fw.graphics.apply_camera(screen.camera, screen.frustum); |
|
268 |
|
loop.models = model.model; |
|
269 |
|
} |
|
270 |
|
}); |
|
271 |
|
|
|
272 |
|
binds.destroy(&fw.compute); |
|
273 |
|
fw.graphics.destroy(model.model.tex.p_data, false); |
|
274 |
|
fw.graphics.destroy(model.model.ver.p_data, false); |
|
275 |
|
|
|
276 |
|
fw.destroy(); |
|
277 |
|
jl::deallocate(&p_pixels); |
|
278 |
|
} |
|
279 |
|
void regenerate() { |
|
280 |
|
jl::time elapsed; |
|
281 |
|
compute(shader_type, &binds, &fw.compute, |
|
282 |
|
reinterpret_cast<Color*>(&p_pixels->data), |
|
283 |
|
reinterpret_cast<Color*>(&p_pixels->computed_data), &elapsed); |
|
284 |
|
|
|
285 |
|
if (model.model.tex.p_data != nullptr) |
|
286 |
|
fw.graphics.destroy(model.model.tex.p_data, false); |
|
287 |
|
jen::vk::Result res; |
|
288 |
|
res = model.init_texture(&fw.graphics, EXTENT, &p_pixels->computed_data); |
|
289 |
|
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
|
290 |
|
} |
|
291 |
|
|
|
292 |
|
constexpr static const math::v3u32 EXTENT = {800,800,1}; |
|
293 |
|
struct Pixels { |
|
294 |
|
jl::array2D<Color, EXTENT.x, EXTENT.y> data, computed_data; |
|
295 |
|
}; |
|
296 |
|
|
|
297 |
|
ShaderType shader_type; |
|
298 |
|
ComputeBindings binds; |
|
299 |
|
Pixels *p_pixels; |
|
300 |
|
jen::Framework fw; |
|
301 |
|
screen::Static screen; |
|
302 |
|
RenderImage model; |
|
303 |
|
jen::Loop loop; |
|
304 |
|
}; |
|
305 |
|
|
|
306 |
|
int main() { |
|
307 |
|
Program program; |
|
308 |
|
program.run(); |
|
309 |
|
return 0; |
|
310 |
|
} |
File src/noise_main.cpp renamed from src/main.cpp (similarity 96%) (mode: 100644) (index 4e23be9..6b42189) |
... |
... |
struct ComputeBindings { |
159 |
159 |
auto &uniform = bindings[0]; |
auto &uniform = bindings[0]; |
160 |
160 |
auto &storage = bindings[1]; |
auto &storage = bindings[1]; |
161 |
161 |
|
|
162 |
|
binds.uniform_texel_buffer = {}; |
|
163 |
|
binds.storage_texel_buffer = {}; |
|
|
162 |
|
binds = {}; |
164 |
163 |
binds.uniform_buffer = uniform; |
binds.uniform_buffer = uniform; |
165 |
164 |
binds.storage_buffer = storage; |
binds.storage_buffer = storage; |
166 |
165 |
return VK_SUCCESS; |
return VK_SUCCESS; |
|
... |
... |
compute_test(ShaderNoiseType noise_type, u32 work_scale, i32 seed, f32 *p_dst, |
194 |
193 |
consts[0] = noise_type; |
consts[0] = noise_type; |
195 |
194 |
consts[1] = work_group_size; |
consts[1] = work_group_size; |
196 |
195 |
vkw::ShaderSpecialization spec; |
vkw::ShaderSpecialization spec; |
197 |
|
spec.p_data = &noise_type; |
|
|
196 |
|
spec.p_data = &consts; |
198 |
197 |
spec.data_size = noise_type_const.size + workgroup_size_const.size; |
spec.data_size = noise_type_const.size + workgroup_size_const.size; |
199 |
|
spec.constants.count = 1; |
|
|
198 |
|
spec.constants.count = shader_consts.count(); |
200 |
199 |
spec.constants.p = shader_consts.begin(); |
spec.constants.p = shader_consts.begin(); |
201 |
200 |
jen::vk::ComputePipeline pipeline; |
jen::vk::ComputePipeline pipeline; |
202 |
201 |
|
|
203 |
202 |
jen::vk::Result res; |
jen::vk::Result res; |
204 |
|
res = p_mc->create_pipeline(p_binds->binds, "shader_comp.spv", |
|
205 |
|
&spec, &pipeline); |
|
|
203 |
|
res = p_mc->create_pipeline(p_binds->binds, "noise.spv", &spec, &pipeline); |
206 |
204 |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
207 |
205 |
|
|
208 |
206 |
jen::vk::BindingsSet set; |
jen::vk::BindingsSet set; |
|
... |
... |
compute_test(ShaderNoiseType noise_type, u32 work_scale, i32 seed, f32 *p_dst, |
229 |
227 |
info.p_pipeline = &pipeline; |
info.p_pipeline = &pipeline; |
230 |
228 |
info.p_bindingsSet = &set; |
info.p_bindingsSet = &set; |
231 |
229 |
info.group_count = {work_groups,1,1}; |
info.group_count = {work_groups,1,1}; |
232 |
|
info.writes.p = &write; |
|
233 |
|
info.writes.count = 1; |
|
234 |
|
info.reads.p = &read; |
|
235 |
|
info.reads.count = 1; |
|
|
230 |
|
info.buffer_writes = write; |
|
231 |
|
info.buffer_reads = read; |
|
232 |
|
info.images_writes = {}; |
|
233 |
|
info.images_reads = {}; |
236 |
234 |
|
|
237 |
235 |
auto start = jl::time::current(); |
auto start = jl::time::current(); |
238 |
236 |
{ |
{ |
239 |
237 |
res = p_mc->compute(info); |
res = p_mc->compute(info); |
240 |
238 |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
241 |
|
res = p_mc->read(p_unit, info.reads); |
|
|
239 |
|
res = p_mc->read(p_unit, info.buffer_reads, {}); |
242 |
240 |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
jassert_release(res == VK_SUCCESS, vkw::to_string(res)); |
243 |
241 |
} |
} |
244 |
242 |
*p_compute_elapsed = start.elapsed(jl::time::current()); |
*p_compute_elapsed = start.elapsed(jl::time::current()); |