• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
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 
16 #ifndef API_RENDER_IRENDER_COMMAND_LIST_H
17 #define API_RENDER_IRENDER_COMMAND_LIST_H
18 
19 #include <cstdint>
20 
21 #include <base/containers/array_view.h>
22 #include <base/math/vector.h>
23 #include <base/util/uid.h>
24 #include <core/plugin/intf_interface.h>
25 #include <render/device/gpu_resource_desc.h>
26 #include <render/namespace.h>
27 #include <render/resource_handle.h>
28 
29 RENDER_BEGIN_NAMESPACE()
30 struct RenderPassDesc;
31 struct RenderPassSubpassDesc;
32 struct PushConstant;
33 struct IndexBuffer;
34 struct VertexBuffer;
35 struct ImageBlit;
36 
37 class IDevice;
38 class ILowLevelDevice;
39 struct RenderBackendRecordingState;
40 
41 /** RenderBackendCommand
42  * Can be used exact command buffer position or with backend positions.
43  */
44 class IRenderBackendCommand : public CORE_NS::IInterface {
45 public:
46     static constexpr auto UID = BASE_NS::Uid("5a9bf1e7-bb10-4011-9b45-83fc7103b49e");
47 
48     using Ptr = BASE_NS::refcnt_ptr<IRenderBackendCommand>;
49 
50     /** ExecuteBackendCommand method to be implemented
51      * @device ILowLevelDevice which can be casted to backend device
52      * @recordingState A recording state
53      */
54     virtual void ExecuteBackendCommand(
55         const ILowLevelDevice& device, const RenderBackendRecordingState& recordingState) = 0;
56 
57 protected:
58     IRenderBackendCommand() = default;
59     virtual ~IRenderBackendCommand() = default;
60 
61     IRenderBackendCommand(const IRenderBackendCommand&) = delete;
62     IRenderBackendCommand& operator=(const IRenderBackendCommand&) = delete;
63     IRenderBackendCommand(IRenderBackendCommand&&) = delete;
64     IRenderBackendCommand& operator=(IRenderBackendCommand&&) = delete;
65 };
66 
67 /** RenderBackendPositionCommand
68  * Can be used in selected positions.
69  */
70 class IRenderBackendPositionCommand : public CORE_NS::IInterface {
71 public:
72     static constexpr auto UID = BASE_NS::Uid("8feb91da-97ee-4a18-be6f-c5d5074bad8f");
73 
74     using Ptr = BASE_NS::refcnt_ptr<IRenderBackendPositionCommand>;
75 
76     /** ExecuteBackendCommand method to be implemented
77      * @device IDevice, low level device accessable through device.GetLowLevelDevice()
78      */
79     virtual void ExecuteBackendCommand(const IDevice& device) = 0;
80 
81 protected:
82     IRenderBackendPositionCommand() = default;
83     virtual ~IRenderBackendPositionCommand() = default;
84 
85     IRenderBackendPositionCommand(const IRenderBackendPositionCommand&) = delete;
86     IRenderBackendPositionCommand& operator=(const IRenderBackendPositionCommand&) = delete;
87     IRenderBackendPositionCommand(IRenderBackendPositionCommand&&) = delete;
88     IRenderBackendPositionCommand& operator=(IRenderBackendPositionCommand&&) = delete;
89 };
90 
91 /** RenderBackendCommandPosition
92  * To position non-command list commands.
93  * The ordering is render node (render command list)
94  */
95 enum class RenderBackendCommandPosition : uint32_t {
96     /** Execute command before automatic backend presentation */
97     BEFORE_PRESENTATION = 0,
98     /** Execute command after automatic backend presentation */
99     AFTER_PRESENTATION = 1,
100     /** Execute command before automatic backend acquire */
101     BEFORE_ACQUIRE = 2,
102 };
103 /** @ingroup group_render_irendercommandlist */
104 /** Call methods to add render commands to a render command list.
105  * Render command list is unique for every render node.
106  * Most of the methods and their inputs are familiar from different graphics APIs.
107  *
108  * RenderCommandList does not do heavy processing on unnecessary state changes etc.
109  * Prefer setting data, bindings etc. only once and do not add empty draw and/or dispatches.
110  */
111 class IRenderCommandList : public CORE_NS::IInterface {
112 public:
113     static constexpr auto UID = BASE_NS::Uid("744d8a3c-82cd-44f5-9fcb-769b33ceca1b");
114 
115     /** Can only be called inside of a render pass.
116      * @param vertexCount Vertex count
117      * @param instanceCount Instance count
118      * @param firstVertex First vertex
119      * @param firstInstance First instance
120      */
121     virtual void Draw(const uint32_t vertexCount, const uint32_t instanceCount, const uint32_t firstVertex,
122         const uint32_t firstInstance) = 0;
123 
124     /** Can only be called inside of a render pass.
125      * @param indexCount Index count
126      * @param instanceCount Instance count
127      * @param firstIndex First index
128      * @param vertexOffset Vertex offset
129      * @param firstInstance First instance
130      */
131     virtual void DrawIndexed(const uint32_t indexCount, const uint32_t instanceCount, const uint32_t firstIndex,
132         const int32_t vertexOffset, const uint32_t firstInstance) = 0;
133 
134     /** Draw with indirect arguments.
135      * Can only be called inside of a render pass.
136      * @param bufferHandle Buffer handle
137      * @param offset Offset
138      * @param drawCount Draw count
139      * @param stride Stride
140      */
141     virtual void DrawIndirect(
142         const RenderHandle bufferHandle, const uint32_t offset, const uint32_t drawCount, const uint32_t stride) = 0;
143 
144     /** Can only be called inside of a render pass.
145      * @param bufferHandle Buffer handle
146      * @param offset Offset
147      * @param drawCount Draw count
148      * @param stride Stride
149      */
150     virtual void DrawIndexedIndirect(
151         const RenderHandle bufferHandle, const uint32_t offset, const uint32_t drawCount, const uint32_t stride) = 0;
152 
153     /** Dispatch a compute program.
154      * @param groupCountX Group count x
155      * @param groupCountY Group count y
156      * @param groupCountZ Group count z
157      */
158     virtual void Dispatch(const uint32_t groupCountX, const uint32_t groupCountY, const uint32_t groupCountZ) = 0;
159 
160     /** Dispatch a compute program with indirect arguments.
161      * @param bufferHandle Buffer handle
162      * @param offset Offset
163      */
164     virtual void DispatchIndirect(const RenderHandle bufferHandle, const uint32_t offset) = 0;
165 
166     /** Bind pipeline
167      * @param psoHandle PSO handle
168      */
169     virtual void BindPipeline(const RenderHandle psoHandle) = 0;
170 
171     /** Push constant. The data is copied.
172      * @param pushConstant Push constant
173      * @param data Data
174      */
175     virtual void PushConstantData(
176         const struct PushConstant& pushConstant, const BASE_NS::array_view<const uint8_t> data) = 0;
177 
178     /** Push constant. The data is copied. Prefer using PushConstantData -method. This will be deprecated.
179      * @param pushConstant Push constant
180      * @param data Data
181      */
182     virtual void PushConstant(const struct PushConstant& pushConstant, const uint8_t* data) = 0;
183 
184     /** Bind vertex buffers
185      * @param vertexBuffers Vertex buffers
186      */
187     virtual void BindVertexBuffers(const BASE_NS::array_view<const VertexBuffer> vertexBuffers) = 0;
188 
189     /** Bind index buffer
190      * @param indexBuffer Index buffer
191      */
192     virtual void BindIndexBuffer(const IndexBuffer& indexBuffer) = 0;
193 
194     /** Draw-calls can only be made inside of a render pass.
195      * A render pass definition without content. Render pass needs to have
196      * SubpassContents::CORE_SUBPASS_CONTENTS_INLINE set.
197      * All subpasses given with subpassDescs.
198      * @param renderPassDesc Render pass descriptor
199      * @param subpassDescs Subpass descriptors
200      */
201     virtual void BeginRenderPass(
202         const RenderPassDesc& renderPassDesc, const BASE_NS::array_view<const RenderPassSubpassDesc> subpassDescs) = 0;
203 
204     /** Draw-calls can only be made inside of a render pass.
205      * A render pass definition without content. Render pass needs to have
206      * SubpassContents::CORE_SUBPASS_CONTENTS_INLINE set.
207      * Subpasses are patched to this render pass from other render command lists, if renderPassDesc.subpassCount > 1.
208      * There cannot be multiple "open" render passes from other render command lists.
209      * @param renderPassDesc Render pass descriptor
210      * @param subpassStartIndex Subpass start index
211      * @param subpassDesc Subpass descriptor
212      */
213     virtual void BeginRenderPass(const RenderPassDesc& renderPassDesc, const uint32_t subpassStartIndex,
214         const RenderPassSubpassDesc& subpassDesc) = 0;
215 
216     /** Must be called when a render pass ends. */
217     virtual void EndRenderPass() = 0;
218 
219     /** Next subpass
220      * @param subpassContents subpass contents
221      */
222     virtual void NextSubpass(const SubpassContents& subpassContents) = 0;
223 
224     /** This will disable automatic barriers until EndExecuteAutomaticBarriers is called.
225      * This will add a barrier point for current pending barriers.
226      * Use when manually adding barriers and executing them in a single spot.
227      * In addition, disables initial image layouts in render passes and uses undefined layouts.
228      */
229     virtual void BeginDisableAutomaticBarrierPoints() = 0;
230 
231     /** Re-enable automatic barriers.
232      * Needs to be called after BeginDisableAutomaticBarrierPoints to re-enable automatic barriers.
233      */
234     virtual void EndDisableAutomaticBarrierPoints() = 0;
235 
236     /** This will add custom barrier point where all pending (custom) barriers will be executed.
237      */
238     virtual void AddCustomBarrierPoint() = 0;
239 
240     /** Add custom memory barrier.
241      * Can be used for a memory barrier.
242      * @param src General barrier source state
243      * @param dst General barrier destination state
244      */
245     virtual void CustomMemoryBarrier(const GeneralBarrier& src, const GeneralBarrier& dst) = 0;
246 
247     /** Add custom barriers for a GPU buffer.
248      * Can only be called outside of render pass.
249      * @param handle Handle to resource
250      * @param src Source buffer resource barrier
251      * @param dst Destination buffer resource barrier
252      * @param byteOffset Byte offset
253      * @param byteSize Byte size (use PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE for the whole buffer)
254      */
255     virtual void CustomBufferBarrier(const RenderHandle handle, const BufferResourceBarrier& src,
256         const BufferResourceBarrier& dst, const uint32_t byteOffset, const uint32_t byteSize) = 0;
257 
258     /** Add custom barriers for a GPU image.
259      * Can only be called outside of render pass.
260      * Checks the current/correct state and layout, and updates to new given dst state.
261      * @param handle Handle to resource
262      * @param dst Destination image resource barrier
263      * @param imageSubresourceRange ImageSubresourceRange
264      */
265     virtual void CustomImageBarrier(const RenderHandle handle, const ImageResourceBarrier& dst,
266         const ImageSubresourceRange& imageSubresourceRange) = 0;
267     /** Add custom barriers for a GPU image.
268      * Can only be called outside of render pass.
269      * Does not check the current/correct state and layout. Can be used e.g. as a barrier from undefined state.
270      * @param handle Handle to resource
271      * @param src Source image resource barrier
272      * @param dst Destination image resource barrier
273      * @param imageSubresourceRange ImageSubresourceRange
274      */
275     virtual void CustomImageBarrier(const RenderHandle handle, const ImageResourceBarrier& src,
276         const ImageResourceBarrier& dst, const ImageSubresourceRange& imageSubresourceRange) = 0;
277 
278     /** Copy buffer to buffer
279      * @param srcHandle Source handle
280      * @param dstHandle Destination handle
281      * @param bufferCopy Buffer copy
282      */
283     virtual void CopyBufferToBuffer(
284         const RenderHandle srcHandle, const RenderHandle dstHandle, const BufferCopy& bufferCopy) = 0;
285 
286     /** Copy buffer to image
287      * @param srcHandle Source handle
288      * @param dstHandle Destination handle
289      * @param bufferImageCopy Buffer image copy
290      */
291     virtual void CopyBufferToImage(
292         const RenderHandle srcHandle, const RenderHandle dstHandle, const BufferImageCopy& bufferImageCopy) = 0;
293 
294     /** Copy image to buffer
295      * @param srcHandle Source handle
296      * @param dstHandle Destination handle
297      * @param bufferImageCopy Buffer image copy
298      */
299     virtual void CopyImageToBuffer(
300         const RenderHandle srcHandle, const RenderHandle dstHandle, const BufferImageCopy& bufferImageCopy) = 0;
301 
302     /** Copy image to image
303      * @param srcHandle Source handle
304      * @param dstHandle Destination handle
305      * @param imageCopy Image copy
306      */
307     virtual void CopyImageToImage(
308         const RenderHandle srcHandle, const RenderHandle dstHandle, const ImageCopy& imageCopy) = 0;
309 
310     /** Blit source image to destination image.
311      * Can only be called outside of render pass.
312      * @param srcImageHandle Source handle
313      * @param dstImageHandle Destination handle
314      * @param imageBlit Image blit
315      * @param filter Filtering mode
316      */
317     virtual void BlitImage(const RenderHandle srcImageHandle, const RenderHandle dstImageHandle,
318         const ImageBlit& imageBlit, const Filter filter) = 0;
319 
320     /** Update a single descriptor set with given bindings.
321      * @param handle Handle used in update
322      * @param bindingResources Binding resources
323      */
324     virtual void UpdateDescriptorSet(
325         const RenderHandle handle, const DescriptorSetLayoutBindingResources& bindingResources) = 0;
326 
327     /** Update descriptor sets with given bindings. Array view sizes must match.
328      * @param handles Handles for descriptor sets
329      * @param bindingResources Binding resources for descriptor sets
330      */
331     virtual void UpdateDescriptorSets(const BASE_NS::array_view<const RenderHandle> handles,
332         const BASE_NS::array_view<const DescriptorSetLayoutBindingResources> bindingResources) = 0;
333 
334     /** Bind a single descriptor set to pipeline. (Might combine consecutive descriptor set bindings)
335      * There can be maximum of 4 sets. I.e. the maximum set index is 3.
336      * @param set Set to bind
337      * @param handle Handle to resource
338      */
339     virtual void BindDescriptorSet(const uint32_t set, const RenderHandle handle) = 0;
340 
341     /** Bind a single descriptor set to pipeline. (Might combine consecutive descriptor set bindings)
342      * There can be maximum of 4 sets. I.e. the maximum set index is 3.
343      * @param set Set to bind
344      * @param handle Handle to resource
345      * @param dynamicOffsets Byte offsets for dynamic descriptors
346      */
347     virtual void BindDescriptorSet(
348         const uint32_t set, const RenderHandle handle, const BASE_NS::array_view<const uint32_t> dynamicOffsets) = 0;
349 
350     /** Bind multiple descriptor sets to pipeline. (Might combine consecutive descriptor set bindings)
351      * There can be maximum of 4 sets. I.e. the maximum set index is 3.
352      * Descriptor sets needs to be a contiguous set.
353      * @param firstSet First set index
354      * @param handles Handles to resources
355      */
356     virtual void BindDescriptorSets(const uint32_t firstSet, const BASE_NS::array_view<const RenderHandle> handles) = 0;
357 
358     /** BindDescriptorSetData
359      */
360     struct BindDescriptorSetData {
361         /** Descriptor set handle */
362         RenderHandle handle;
363         /** Descriptor set dynamic buffer offsets */
364         BASE_NS::array_view<const uint32_t> dynamicOffsets;
365     };
366 
367     /** Bind a single descriptor set to pipeline. (Might combine consecutive descriptor set bindings)
368      * There can be maximum of 4 sets. I.e. the maximum set index is 3.
369      * @param set Set to bind
370      * @param descriptorSetData Descriptor set data
371      */
372     virtual void BindDescriptorSet(const uint32_t set, const BindDescriptorSetData& desriptorSetData) = 0;
373 
374     /** Bind multiple descriptor sets to pipeline some with dynamic offsets. (Might combine consecutive descriptor set
375      * bindings.) There can be maximum of 4 sets. I.e. the maximum set index is 3. Descriptor sets needs to be a
376      * contiguous set.
377      * @param firstSet First set index
378      * @param descriptorSetData Descriptor set data
379      */
380     virtual void BindDescriptorSets(
381         const uint32_t firstSet, const BASE_NS::array_view<const BindDescriptorSetData> descriptorSetData) = 0;
382 
383     /** Build acceleration structures
384      * @param geometry Acceleration structure build geometry data
385      * @param triangles Geometry triangles
386      * @param aabbs Geometry aabbs
387      * @param instances Geometry instances
388      */
389     virtual void BuildAccelerationStructures(const AsBuildGeometryData& geometry,
390         const BASE_NS::array_view<const AsGeometryTrianglesData> triangles,
391         const BASE_NS::array_view<const AsGeometryAabbsData> aabbs,
392         const BASE_NS::array_view<const AsGeometryInstancesData> instances) = 0;
393 
394     /** Copy acceleration structure instances to instance data
395      * @param destination Buffer handle with offset
396      * @param instances Instances which will copied to the buffer
397      */
398     virtual void CopyAccelerationStructureInstances(
399         const BufferOffset& destination, BASE_NS::array_view<const AsInstance> instances) = 0;
400 
401     /** Clear color image.
402      * This should only be needed when initializing images to some values.
403      * Often render pass attachment clears and shader clears are needed.
404      * Some backends might not support this, i.e. one might need to use higher level paths for e.g. OpenGLES
405      * @param handle Handle of the image
406      * @param color Clear color values
407      * @param ranges Array view of image subresource ranges
408      */
409     virtual void ClearColorImage(const RenderHandle handle, const ClearColorValue color,
410         const BASE_NS::array_view<const ImageSubresourceRange> ranges) = 0;
411 
412     /** Set dynamic state viewport
413      * @param viewportDesc Viewport descriptor
414      */
415     virtual void SetDynamicStateViewport(const ViewportDesc& viewportDesc) = 0;
416 
417     /** Set dynamic state scissor
418      * @param scissorDesc Scissor descriptor
419      */
420     virtual void SetDynamicStateScissor(const ScissorDesc& scissorDesc) = 0;
421 
422     /** Set dynamic state line width
423      * @param lineWidth Line width
424      */
425     virtual void SetDynamicStateLineWidth(const float lineWidth) = 0;
426 
427     /** Set dynamic state depth bias
428      * @param depthBiasConstantFactor Depth bias constant factor
429      * @param depthBiasClamp Depth bias clamp
430      * @param depthBiasSlopeFactor Depth bias slope factor
431      */
432     virtual void SetDynamicStateDepthBias(
433         const float depthBiasConstantFactor, const float depthBiasClamp, const float depthBiasSlopeFactor) = 0;
434 
435     /** Set dynamic state blend constants
436      * @param blendConstants Blend constants
437      */
438     virtual void SetDynamicStateBlendConstants(const BASE_NS::array_view<const float> blendConstants) = 0;
439 
440     /** Set dynamic state depth bounds
441      * @param minDepthBounds Min depth bounds
442      * @param maxDepthBounds Max depth bounds
443      */
444     virtual void SetDynamicStateDepthBounds(const float minDepthBounds, const float maxDepthBounds) = 0;
445 
446     /** Set dynamic state stencil compare mask
447      * @param faceMask Face mask
448      * @param compareMask Compare mask
449      */
450     virtual void SetDynamicStateStencilCompareMask(const StencilFaceFlags faceMask, const uint32_t compareMask) = 0;
451 
452     /** Set dynamic state stencil write mask
453      * @param faceMask Face mask
454      * @param writeMask Write mask
455      */
456     virtual void SetDynamicStateStencilWriteMask(const StencilFaceFlags faceMask, const uint32_t writeMask) = 0;
457 
458     /** Set dynamic state stencil reference
459      * @param faceMask Face mask
460      * @param reference Reference
461      */
462     virtual void SetDynamicStateStencilReference(const StencilFaceFlags faceMask, const uint32_t reference) = 0;
463 
464     /** Set dynamic state fragmend shading rate.
465      * @param fragmentSize Fragment size, pipeline fragment shading rate. (Valid values 1, 2, 4)
466      * @param combinerOps Combiner operations
467      */
468     virtual void SetDynamicStateFragmentShadingRate(
469         const Size2D& fragmentSize, const FragmentShadingRateCombinerOps& combinerOps) = 0;
470 
471     /** [[DEPRECATED]] Set execute backend frame position. The position where the method is ran.
472      * Often this might be the only command in the render command list, when using backend nodes.
473      * This can be set only once during render command list setup per frame.
474      */
475     // [[DEPRECATED]] use SetExecuteBackendCommand(...)
476     [[deprecated]] virtual void SetExecuteBackendFramePosition() = 0;
477 
478     /** Set execute backend command. The command will be run in this position when backend is run.
479      * @param backendCommand A command / method which is run during the backend phase.
480      */
481     virtual void SetExecuteBackendCommand(IRenderBackendCommand::Ptr backendCommand) = 0;
482 
483     /** Set backend command to a specific frame position.
484      * @param backendCommand A command / method which is run during the backend phase.
485      * @param backendCommandPosition A command / method which is run during the backend phase.
486      */
487     virtual void SetBackendCommand(
488         IRenderBackendPositionCommand::Ptr backendCommand, RenderBackendCommandPosition backendCommandPosition) = 0;
489 
490     /** Begin render debug marker (works only when RENDER_DEBUG_MARKERS_ENABLED is 1)
491      * Can be visualized with different graphics tools.
492      * Default color is white.
493      * @param name Name of the marker
494      */
495     virtual void BeginDebugMarker(const BASE_NS::string_view name) = 0;
496 
497     /** Begin render debug marker (works only when RENDER_DEBUG_MARKERS_ENABLED is 1)
498      * Can be visualized with different graphics tools.
499      * @param name Name of the marker
500      * @param color Color of the marker
501      */
502     virtual void BeginDebugMarker(const BASE_NS::string_view name, const BASE_NS::Math::Vec4 color) = 0;
503 
504     /** Ends the debug marker.
505      */
506     virtual void EndDebugMarker() = 0;
507 
508 protected:
509     IRenderCommandList() = default;
510     virtual ~IRenderCommandList() = default;
511 
512     IRenderCommandList(const IRenderCommandList&) = delete;
513     IRenderCommandList& operator=(const IRenderCommandList&) = delete;
514     IRenderCommandList(IRenderCommandList&&) = delete;
515     IRenderCommandList& operator=(IRenderCommandList&&) = delete;
516 };
517 
518 #if (RENDER_DEBUG_MARKERS_ENABLED == 1)
519 
520 class RenderCommandListDebugMarkerScope final {
521 public:
522     inline RenderCommandListDebugMarkerScope(IRenderCommandList& cmdList, const BASE_NS::string_view name);
523     inline RenderCommandListDebugMarkerScope(
524         IRenderCommandList& cmdList, const BASE_NS::string_view name, const BASE_NS::Math::Vec4 color);
525     inline ~RenderCommandListDebugMarkerScope();
526 
527 protected:
528     IRenderCommandList& cmdList_;
529 };
530 
RenderCommandListDebugMarkerScope(IRenderCommandList & cmdList,const BASE_NS::string_view name)531 inline RenderCommandListDebugMarkerScope::RenderCommandListDebugMarkerScope(
532     IRenderCommandList& cmdList, const BASE_NS::string_view name)
533     : cmdList_(cmdList)
534 {
535     cmdList_.BeginDebugMarker(name);
536 }
537 
RenderCommandListDebugMarkerScope(IRenderCommandList & cmdList,const BASE_NS::string_view name,const BASE_NS::Math::Vec4 color)538 inline RenderCommandListDebugMarkerScope::RenderCommandListDebugMarkerScope(
539     IRenderCommandList& cmdList, const BASE_NS::string_view name, const BASE_NS::Math::Vec4 color)
540     : cmdList_(cmdList)
541 {
542     cmdList_.BeginDebugMarker(name, color);
543 }
544 
~RenderCommandListDebugMarkerScope()545 inline RenderCommandListDebugMarkerScope::~RenderCommandListDebugMarkerScope()
546 {
547     cmdList_.EndDebugMarker();
548 }
549 
550 // Helper to concatenate macro values.
551 #define RENDER_CMD_LIST_CONCAT_NOEXP(value0, value1) value0##value1
552 #define RENDER_CMD_LIST_CONCAT(value0, value1) RENDER_CMD_LIST_CONCAT_NOEXP(value0, value1)
553 
554 #define RENDER_DEBUG_MARKER_SCOPE(cmdList, name) \
555     RENDER_NS::RenderCommandListDebugMarkerScope RENDER_CMD_LIST_CONCAT(rclDebugMarkerScope, __LINE__)(cmdList, name)
556 #define RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, name, color)                                                  \
557     RENDER_NS::RenderCommandListDebugMarkerScope RENDER_CMD_LIST_CONCAT(rclDebugMarkerColorScope, __LINE__)( \
558         cmdList, name, color)
559 
560 #else
561 #define RENDER_DEBUG_MARKER_SCOPE(cmdList, name)
562 #define RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, name, color)
563 #endif
564 RENDER_END_NAMESPACE()
565 
566 #endif // API_RENDER_IRENDER_COMMAND_LIST_H
567