diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2022-11-16 14:53:04 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-16 14:53:04 -0300 |
| commit | f1d1670b0b1b5c08064df95dabd295f3cf5dcf7f (patch) | |
| tree | 082139cb80ee9776f3ea9083991fb3ed6618f7f4 /Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp | |
| parent | b8de72de8f25f0bb7f994bc07a0387c1c247b6fe (diff) | |
Implement HLE macro for DrawElementsIndirect (#3748)
* Implement HLE macro for DrawElementsIndirect
* Shader cache version bump
* Use GL_ARB_shader_draw_parameters extension on OpenGL
* Fix DrawIndexedIndirectCount on Vulkan when extension is not supported
* Implement DrawIndex
* Alignment
* Fix some validation errors
* Rename BaseIds to DrawParameters
* Fix incorrect index buffer and vertex buffer size in some cases
* Add HLE macros for DrawArraysInstanced and DrawElementsInstanced
* Perform a regular draw when indirect data is not modified
* Use non-indirect draw methods if indirect buffer was not GPU modified
* Only check if draw parameters match if the shader actually uses them
* Expose Macro HLE setting on GUI
* Reset FirstVertex and FirstInstance after draw
* Update shader cache version again since some people already tested this
* PR feedback
Co-authored-by: riperiperi <rhy3756547@hotmail.com>
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp')
| -rw-r--r-- | Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp b/Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp new file mode 100644 index 00000000..6ee96b7b --- /dev/null +++ b/Ryujinx.Graphics.Vulkan/Shaders/ConvertIndirectDataShaderSource.comp @@ -0,0 +1,103 @@ +#version 450 core + +#extension GL_EXT_scalar_block_layout : require + +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout (std430, set = 0, binding = 0) uniform draw_count_uniform +{ + uint[64] draw_count_buffer; +}; + +layout (std430, set = 1, binding = 1) buffer indirect_in +{ + int[] indirect_data_in; +}; + +layout (std430, set = 1, binding = 2) buffer indirect_out +{ + int[] indirect_data_out; +}; + +layout (std430, set = 1, binding = 3) buffer index_buffer_pattern +{ + int ibp_pattern[8]; + int ibp_primitive_vertices; + int ibp_primitive_vertices_out; + int ibp_index_size; + int ibp_index_size_out; + int ibp_base_index; + int ibp_index_stride; + int src_offset; + int total_primitives; + int dispatch_x; + int dispatch_y; + int dispatch_z; + int has_draw_count; + uint max_draw_count; + int draw_count_offset; + int indirect_data_stride; + int indirect_data_offset; +}; + +int GetPrimitiveCount(int vertexCount) +{ + return max(0, (vertexCount - ibp_base_index) / ibp_index_stride); +} + +int GetConvertedCount(int indexCount) +{ + int primitiveCount = GetPrimitiveCount(indexCount); + return primitiveCount * ibp_primitive_vertices_out; +} + +void main() +{ + uint drawCount = has_draw_count != 0 ? min(draw_count_buffer[draw_count_offset], max_draw_count) : max_draw_count; + uint i = 0; + + if (drawCount != 0) + { + int firstIndex = indirect_data_in[indirect_data_offset + 2]; + int endIndex = firstIndex + indirect_data_in[indirect_data_offset]; + + for (i = 1; i < drawCount; i++) + { + int offset = int(i) * indirect_data_stride; + int inOffset = indirect_data_offset + offset; + + int currentFirstIndex = indirect_data_in[inOffset + 2]; + firstIndex = min(firstIndex, currentFirstIndex); + endIndex = max(endIndex, currentFirstIndex + indirect_data_in[inOffset]); + } + + int indexCount = endIndex - firstIndex; + + dispatch_x = (indexCount + 15) / 16; + src_offset += firstIndex * ibp_index_size; + total_primitives = GetPrimitiveCount(indexCount); + + for (i = 0; i < drawCount; i++) + { + int offset = int(i) * indirect_data_stride; + int inOffset = indirect_data_offset + offset; + + indirect_data_out[offset] = GetConvertedCount(indirect_data_in[inOffset]); // Index count + indirect_data_out[offset + 1] = indirect_data_in[inOffset + 1]; // Instance count + indirect_data_out[offset + 2] = GetConvertedCount(indirect_data_in[inOffset + 2] - firstIndex); // First index + indirect_data_out[offset + 3] = indirect_data_in[inOffset + 3]; // Vertex offset + indirect_data_out[offset + 4] = indirect_data_in[inOffset + 4]; // First instance + } + } + + for (; i < max_draw_count; i++) + { + int offset = int(i) * indirect_data_stride; + + indirect_data_out[offset] = 0; + indirect_data_out[offset + 1] = 0; + indirect_data_out[offset + 2] = 0; + indirect_data_out[offset + 3] = 0; + indirect_data_out[offset + 4] = 0; + } +} |
