diff --git a/demo/gl/tz_bloom_demo.cpp b/demo/gl/tz_bloom_demo.cpp index 57f7260d28..7cfe397716 100644 --- a/demo/gl/tz_bloom_demo.cpp +++ b/demo/gl/tz_bloom_demo.cpp @@ -66,7 +66,10 @@ int main() }); tz::gl::ImageResource image_out1 = image_out0; - tz::gl::BufferResource bloom_data_buffer = tz::gl::BufferResource::from_one(BloomOptions{}, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource bloom_data_buffer = tz::gl::BufferResource::from_one(BloomOptions{}, + { + .access = tz::gl::ResourceAccess::DynamicFixed + }); tz::gl::RendererInfo combine_info; tz::gl::ResourceHandle bloom_data_handle = combine_info.add_resource(bloom_data_buffer); @@ -77,7 +80,10 @@ int main() tz::gl::Renderer combine = tz::gl::device().create_renderer(combine_info); // Firstly draw some shapes. Brighter pixels are written into a second colour attachment - tz::gl::BufferResource render_data = tz::gl::BufferResource::from_one(RenderData{}, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource render_data = tz::gl::BufferResource::from_one(RenderData{}, + { + .access = tz::gl::ResourceAccess::DynamicFixed + }); tz::gl::RendererInfo rinfo; rinfo.shader().set_shader(tz::gl::ShaderStage::Vertex, ImportedShaderSource(tz_bloom_demo, vertex)); diff --git a/demo/gl/tz_blur_triangle_demo.cpp b/demo/gl/tz_blur_triangle_demo.cpp index 8afa12a178..747dd7c614 100644 --- a/demo/gl/tz_blur_triangle_demo.cpp +++ b/demo/gl/tz_blur_triangle_demo.cpp @@ -27,7 +27,10 @@ int main() float pad0[2]; }; - tz::gl::BufferResource blur_data = tz::gl::BufferResource::from_one(BlurData{}, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource blur_data = tz::gl::BufferResource::from_one(BlurData{}, + { + .access = tz::gl::ResourceAccess::DynamicFixed + }); tz::gl::ImageResource blur_image = tz::gl::ImageResource::from_uninitialised ({ .format = tz::gl::ImageFormat::BGRA32, diff --git a/demo/gl/tz_compute_demo.cpp b/demo/gl/tz_compute_demo.cpp index 20dda15939..8015062c78 100644 --- a/demo/gl/tz_compute_demo.cpp +++ b/demo/gl/tz_compute_demo.cpp @@ -19,12 +19,14 @@ int main() }); { tz::gl::BufferResource colour_buffer = tz::gl::BufferResource::from_many - ({ - tz::Vec4{0.0f, 0.0f, 0.0f, 1.0f}, - tz::Vec4{1.0f, 0.0f, 0.0f, 1.0f}, - tz::Vec4{0.0f, 1.0f, 0.0f, 1.0f}, - tz::Vec4{0.0f, 0.0f, 1.0f, 1.0f} - }); + ( + { + tz::Vec4{0.0f, 0.0f, 0.0f, 1.0f}, + tz::Vec4{1.0f, 0.0f, 0.0f, 1.0f}, + tz::Vec4{0.0f, 1.0f, 0.0f, 1.0f}, + tz::Vec4{0.0f, 0.0f, 1.0f, 1.0f} + } + ); tz::gl::BufferResource time_buffer = tz::gl::BufferResource::from_one(0u); tz::gl::RendererInfo pinfo; diff --git a/demo/gl/tz_dynamic_triangle_demo.cpp b/demo/gl/tz_dynamic_triangle_demo.cpp index 21738ed2d0..3a9557e51c 100644 --- a/demo/gl/tz_dynamic_triangle_demo.cpp +++ b/demo/gl/tz_dynamic_triangle_demo.cpp @@ -71,15 +71,24 @@ int main() std::size_t triangle_count = 1; tz::gl::BufferResource buf = tz::gl::BufferResource::from_many - ({ - TriangleVertexData{.position = {-0.5f, -0.5f, 0.0f}, .texcoord = {0.0f, 0.0f}}, - TriangleVertexData{.position = {0.0f, 0.5f, 0.0f}, .texcoord = {0.5f, 1.0f}}, - TriangleVertexData{.position = {0.5f, -0.5f, 0.0f}, .texcoord = {1.0f, 0.0f}}, - }, tz::gl::ResourceAccess::DynamicVariable); + ( + { + TriangleVertexData{.position = {-0.5f, -0.5f, 0.0f}, .texcoord = {0.0f, 0.0f}}, + TriangleVertexData{.position = {0.0f, 0.5f, 0.0f}, .texcoord = {0.5f, 1.0f}}, + TriangleVertexData{.position = {0.5f, -0.5f, 0.0f}, .texcoord = {1.0f, 0.0f}}, + }, + { + .access = tz::gl::ResourceAccess::DynamicVariable + } + ); tz::gl::BufferResource ibuf = tz::gl::BufferResource::from_many - ({ - 0u, 1u, 2u - }, tz::gl::ResourceAccess::DynamicVariable, {tz::gl::ResourceFlag::IndexBuffer}); + ( + {0u, 1u, 2u}, + { + .access = tz::gl::ResourceAccess::DynamicVariable, + .flags = {tz::gl::ResourceFlag::IndexBuffer} + } + ); tz::gl::RendererInfo rinfo; rinfo.shader().set_shader(tz::gl::ShaderStage::Vertex, ImportedShaderSource(tz_dynamic_triangle_demo, vertex)); diff --git a/demo/gl/tz_terrain_demo.cpp b/demo/gl/tz_terrain_demo.cpp index 500d9a728b..2e8783460f 100644 --- a/demo/gl/tz_terrain_demo.cpp +++ b/demo/gl/tz_terrain_demo.cpp @@ -35,8 +35,14 @@ int main() }; - tz::gl::BufferResource buf = tz::gl::BufferResource::from_one(BufferData{}, tz::gl::ResourceAccess::DynamicFixed); - tz::gl::BufferResource buf2 = tz::gl::BufferResource::from_one(FeedbackData{}, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource buf = tz::gl::BufferResource::from_one(BufferData{}, + { + .access = tz::gl::ResourceAccess::DynamicFixed + }); + tz::gl::BufferResource buf2 = tz::gl::BufferResource::from_one(FeedbackData{}, + { + tz::gl::ResourceAccess::DynamicFixed + }); tz::gl::RendererInfo rinfo; tz::gl::ResourceHandle bufh = rinfo.add_resource(buf); diff --git a/src/tz/dbgui/dbgui.cpp b/src/tz/dbgui/dbgui.cpp index bc2b8847bd..17d53f773f 100644 --- a/src/tz/dbgui/dbgui.cpp +++ b/src/tz/dbgui/dbgui.cpp @@ -313,9 +313,18 @@ namespace tz::dbgui // IB and VB have initial size of 1KiB. struct Kibibyte{char d[1024];}; - tz::gl::BufferResource vertex_buffer = tz::gl::BufferResource::from_one(Kibibyte{}, tz::gl::ResourceAccess::DynamicVariable); - tz::gl::BufferResource index_buffer = tz::gl::BufferResource::from_one(Kibibyte{}, tz::gl::ResourceAccess::DynamicVariable); - tz::gl::BufferResource shader_data_buffer = tz::gl::BufferResource::from_one(TopazShaderRenderData{}, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource vertex_buffer = tz::gl::BufferResource::from_one(Kibibyte{}, + { + .access = tz::gl::ResourceAccess::DynamicVariable + }); + tz::gl::BufferResource index_buffer = tz::gl::BufferResource::from_one(Kibibyte{}, + { + .access = tz::gl::ResourceAccess::DynamicVariable + }); + tz::gl::BufferResource shader_data_buffer = tz::gl::BufferResource::from_one(TopazShaderRenderData{}, + { + .access = tz::gl::ResourceAccess::DynamicFixed + }); tz::gl::ImageResource font_image = tz::gl::ImageResource::from_memory ( diff --git a/src/tz/gl/resource.hpp b/src/tz/gl/resource.hpp index 73384b767c..7c5ce8e948 100644 --- a/src/tz/gl/resource.hpp +++ b/src/tz/gl/resource.hpp @@ -33,6 +33,12 @@ namespace tz::gl ResourceFlags flags; }; + struct BufferInfo + { + ResourceAccess access = ResourceAccess::StaticFixed; + ResourceFlags flags = {}; + }; + /** * @ingroup tz_gl2_res * Represents a fixed-size, static Buffer to be used by a Renderer or Processor. @@ -43,30 +49,38 @@ namespace tz::gl virtual ~BufferResource() = default; /** * Create a BufferResource where the underlying data is a single object. + * @note You should be able to optionally pass in braced-initializer-list expressions in for the data, so long as the types of the elements are easily deduceable. * @tparam T Object type. It must be TriviallyCopyable. * @param data Object value to store within the underlying data. - * @param access Specifies access rules after the resource is created under a renderer. - * @param flags An enum-field of @ref ResourceFlag. + * @param info Buffer info, see @ref BufferInfo for details. * @return BufferResource containing a copy of the provided object. */ template - static BufferResource from_one(const T& data, ResourceAccess access = ResourceAccess::StaticFixed, ResourceFlags flags = {}); + static BufferResource from_one(const T& data, BufferInfo info = {}); template - static BufferResource from_many(std::initializer_list ts, ResourceAccess access = ResourceAccess::StaticFixed, ResourceFlags flags = {}) + static BufferResource from_many(std::initializer_list ts, BufferInfo info = {}) { - return from_many(std::span(ts), access, flags); + return from_many(std::span(ts), info); } /** * Create a BufferResource where the underlying data is an array of objects. - * @tparam T Array element type. It must be TriviallyCopyable. - * @param data View into an array. The data will be copied from this span into the underlying buffer data. - * @param access Specifies access rules after the resource is created under a renderer. - * @param flags An enum-field of @ref ResourceFlag. + * @tparam R Type satisfying std::contiguous_range. + * @param data A range of elements of some type. + * @param info Buffer info. See @ref BufferInfo for details. * @return BufferResource containing a copy of the provided array. */ template - static BufferResource from_many(R&& data, ResourceAccess access = ResourceAccess::StaticFixed, ResourceFlags flags = {}); + static BufferResource from_many(R&& data, BufferInfo info = {}); + /** + * Create a null BufferResource. It is not practically useful, aside from as a placeholder. + * + * Null BufferResources are guaranteed to not have size() zero, but its contents and size are implementation-defined. It is also guaranteed to be StaticFixed and have no flags. + */ + static BufferResource null() + { + return from_one(0, {}); + } virtual std::unique_ptr unique_clone() const final; private: BufferResource(ResourceAccess access, std::vector resource_data, std::size_t initial_alignment_offset, ResourceFlags flags); diff --git a/src/tz/gl/resource.inl b/src/tz/gl/resource.inl index 359eb57721..9ae8171390 100644 --- a/src/tz/gl/resource.inl +++ b/src/tz/gl/resource.inl @@ -6,13 +6,13 @@ namespace tz::gl { template - BufferResource BufferResource::from_one(const T& data, ResourceAccess access, ResourceFlags flags) + BufferResource BufferResource::from_one(const T& data, BufferInfo info) { - return BufferResource::from_many({data}, access, flags); + return BufferResource::from_many({data}, info); } template - BufferResource BufferResource::from_many(R&& data, ResourceAccess access, ResourceFlags flags) + BufferResource BufferResource::from_many(R&& data, BufferInfo info) { using T = decltype(*std::ranges::begin(data)); auto size = std::distance(std::ranges::begin(data), std::ranges::end(data)); @@ -29,7 +29,7 @@ namespace tz::gl std::size_t alignment_usage = space_copy - space; // space is now reduced by `alignment_usage` bytes, meaning that when we resize the vector to `space` bytes it is guaranteed to be less than or equal to its initial size. C++ spec says that "Vector capacity is never reduced when resizing to a smaller size because that would invalidate all iterators..." meaning that no realloc took place and the memcpy'd object is still aligned properly. resource_data.resize(space); - return {access, resource_data, alignment_usage, flags}; + return {info.access, resource_data, alignment_usage, info.flags}; } ImageResource ImageResource::from_memory(std::ranges::contiguous_range auto data, ImageInfo info) diff --git a/test/gl/tz_renderer_test.cpp b/test/gl/tz_renderer_test.cpp index 50dd27fc23..b4b81a86a8 100644 --- a/test/gl/tz_renderer_test.cpp +++ b/test/gl/tz_renderer_test.cpp @@ -60,7 +60,10 @@ void renderer_creation_index_buffer(tz::gl::Device& dev) { tz::window().begin_frame(); tz::gl::BufferResource bres0 = tz::gl::BufferResource::from_one(5.0f); - tz::gl::BufferResource ibuf = tz::gl::BufferResource::from_one(0u, tz::gl::ResourceAccess::StaticFixed, {tz::gl::ResourceFlag::IndexBuffer}); + tz::gl::BufferResource ibuf = tz::gl::BufferResource::from_one(0u, + { + .flags = {tz::gl::ResourceFlag::IndexBuffer} + }); tz::gl::RendererInfo rinfo1 = get_empty(); tz::gl::Renderer renderer1 = dev.create_renderer(rinfo1); @@ -76,7 +79,7 @@ void renderer_creation_index_buffer(tz::gl::Device& dev) void renderer_edit(tz::gl::Device& dev) { - tz::gl::BufferResource bres0 = tz::gl::BufferResource::from_many({5.0f, 6.0f}, tz::gl::ResourceAccess::DynamicVariable); + tz::gl::BufferResource bres0 = tz::gl::BufferResource::from_many({5.0f, 6.0f}, {.access = tz::gl::ResourceAccess::DynamicVariable}); tz::gl::RendererInfo rinfo1 = get_empty(); tz::gl::ResourceHandle bh = rinfo1.add_resource(bres0); @@ -134,8 +137,8 @@ void renderer_edit_resource_writes() std::array bufs { tz::gl::BufferResource::from_one(D{}), - tz::gl::BufferResource::from_one(D{}, tz::gl::ResourceAccess::DynamicFixed), - tz::gl::BufferResource::from_one(D{}, tz::gl::ResourceAccess::DynamicVariable) + tz::gl::BufferResource::from_one(D{}, {.access = tz::gl::ResourceAccess::DynamicFixed}), + tz::gl::BufferResource::from_one(D{}, {.access = tz::gl::ResourceAccess::DynamicVariable}) }; std::array imgs @@ -223,7 +226,7 @@ void wireframe_toggle(tz::gl::Device& dev) void renderer_compute_test(tz::gl::Device& dev) { - tz::gl::BufferResource number = tz::gl::BufferResource::from_one(1.0f, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource number = tz::gl::BufferResource::from_one(1.0f, {.access = tz::gl::ResourceAccess::DynamicFixed}); tz::gl::RendererInfo rinfo; rinfo.shader().set_shader(tz::gl::ShaderStage::Compute, ImportedShaderSource(six_writer, compute)); @@ -242,7 +245,7 @@ void renderer_compute_test(tz::gl::Device& dev) void resource_references_compute_test(tz::gl::Device& dev) { - tz::gl::BufferResource number = tz::gl::BufferResource::from_one(1.0f, tz::gl::ResourceAccess::DynamicFixed); + tz::gl::BufferResource number = tz::gl::BufferResource::from_one(1.0f, {.access = tz::gl::ResourceAccess::DynamicFixed}); tz::gl::RendererInfo rinfo; rinfo.shader().set_shader(tz::gl::ShaderStage::Compute, ImportedShaderSource(six_writer, compute)); diff --git a/test/gl/tz_resource_test.cpp b/test/gl/tz_resource_test.cpp index 3973e5f2b1..cb7a727897 100644 --- a/test/gl/tz_resource_test.cpp +++ b/test/gl/tz_resource_test.cpp @@ -14,7 +14,7 @@ void api_correctness() using namespace tz::gl; // Static fixed resources. { - BufferResource bres0 = BufferResource::from_one(0, ResourceAccess::StaticFixed); + BufferResource bres0 = BufferResource::from_one(0, {.access = tz::gl::ResourceAccess::StaticFixed}); tz_assert(bres0.get_type() == ResourceType::Buffer, "BufferResource does not have ResourceType::Buffer"); tz_assert(bres0.get_access() == ResourceAccess::StaticFixed, "StaticFixed BufferResource does not have ResourceAccess::StaticFixed"); @@ -34,7 +34,7 @@ void api_correctness() } // DynamicFixed resources { - BufferResource bres0 = BufferResource::from_one(0, ResourceAccess::DynamicFixed); + BufferResource bres0 = BufferResource::from_one(0, {.access = ResourceAccess::DynamicFixed}); tz_assert(bres0.get_type() == ResourceType::Buffer, "BufferResource does not have ResourceType::Buffer"); tz_assert(bres0.get_access() == ResourceAccess::DynamicFixed, "DynamicFixed BufferResource does not have ResourceAccess::DynamicFixed"); @@ -49,7 +49,7 @@ void api_correctness() } // DynamicVariable resources { - BufferResource bres0 = BufferResource::from_one(0, ResourceAccess::DynamicVariable); + BufferResource bres0 = BufferResource::from_one(0, {.access = ResourceAccess::DynamicVariable}); tz_assert(bres0.get_type() == ResourceType::Buffer, "BufferResource does not have ResourceType::Buffer"); tz_assert(bres0.get_access() == ResourceAccess::DynamicVariable, "DynamicVariable BufferResource does not have ResourceAccess::DynamicVariable"); @@ -69,7 +69,7 @@ void data_correctness() { using namespace tz::gl; // Ensure buffer resource has expected size/data when it has one element. - BufferResource buf = BufferResource::from_one(420.69f, ResourceAccess::StaticFixed); + BufferResource buf = BufferResource::from_one(420.69f); tz_assert(buf.data().size_bytes() == sizeof(float), "BufferResource (one) had unexpected size. Expected %u, got %zu", sizeof(float), buf.data().size_bytes()); tz_assert(buf.data_as().front() == 420.69f, "BufferResource (one) had invalid data. Expected float value %.2f, got %.2f", 420.69f, buf.data_as().front()); // Ensure buffer resource has expected size/data when it has many elements. BufferResource buf0 = BufferResource::from_many @@ -77,7 +77,7 @@ void data_correctness() 0, 1, 2 - }, ResourceAccess::StaticFixed); + }); std::span buf0_data = buf0.data_as(); tz_assert(buf0_data.size() == 3, "BufferResource (many) has unexpected size. Expected %u ints, got %zu ints (%u bytes, %zu bytes)", 3u, buf0_data.size(), 3u * sizeof(int), buf0_data.size_bytes()); for(std::size_t i = 0; i < 3; i++)