mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Port hakuX Phase 2 bindless descriptor indexing
This commit is contained in:
@@ -837,11 +837,19 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
ps->state->smooth_shading, true, false, false);
|
||||
|
||||
if (ps->opts.vulkan) {
|
||||
mstring_append_fmt(
|
||||
preflight,
|
||||
"layout(location = 0) out vec4 fragColor;\n"
|
||||
"layout(binding = %d, std140) uniform PshUniforms {\n",
|
||||
ps->opts.ubo_binding);
|
||||
if (ps->opts.ubo_set > 0) {
|
||||
mstring_append_fmt(
|
||||
preflight,
|
||||
"layout(location = 0) out vec4 fragColor;\n"
|
||||
"layout(set = %d, binding = %d, std140) uniform PshUniforms {\n",
|
||||
ps->opts.ubo_set, ps->opts.ubo_binding);
|
||||
} else {
|
||||
mstring_append_fmt(
|
||||
preflight,
|
||||
"layout(location = 0) out vec4 fragColor;\n"
|
||||
"layout(binding = %d, std140) uniform PshUniforms {\n",
|
||||
ps->opts.ubo_binding);
|
||||
}
|
||||
} else {
|
||||
mstring_append_fmt(preflight,
|
||||
"layout(location = 0) out vec4 fragColor;\n");
|
||||
@@ -870,6 +878,18 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
mstring_append(preflight, "};\n");
|
||||
}
|
||||
|
||||
if (ps->opts.bindless) {
|
||||
mstring_append(preflight,
|
||||
"layout(set = 0, binding = 0) uniform sampler2D texArray2D[1024];\n"
|
||||
"layout(set = 0, binding = 1) uniform sampler3D texArray3D[1024];\n"
|
||||
"layout(set = 0, binding = 2) uniform samplerCube texArrayCube[1024];\n");
|
||||
mstring_append_fmt(preflight,
|
||||
"layout(push_constant) uniform TexPushData {\n"
|
||||
" layout(offset = %d) uint texIdx[4];\n"
|
||||
"};\n",
|
||||
ps->opts.tex_push_offset);
|
||||
}
|
||||
|
||||
const char *dotmap_funcs[] = {
|
||||
"dotmap_zero_to_one",
|
||||
"dotmap_minus1_to_1_d3d",
|
||||
@@ -1402,10 +1422,26 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
}
|
||||
|
||||
if (sampler_type != NULL) {
|
||||
if (ps->opts.vulkan) {
|
||||
mstring_append_fmt(preflight, "layout(binding = %d) ", ps->opts.tex_binding + i);
|
||||
if (ps->opts.bindless) {
|
||||
const char *array_name;
|
||||
if (strcmp(sampler_type, "sampler3D") == 0) {
|
||||
array_name = "texArray3D";
|
||||
} else if (strcmp(sampler_type, "samplerCube") == 0) {
|
||||
array_name = "texArrayCube";
|
||||
} else {
|
||||
array_name = "texArray2D";
|
||||
}
|
||||
mstring_append_fmt(preflight,
|
||||
"#define texSamp%d %s[texIdx[%d]]\n",
|
||||
i, array_name, i);
|
||||
} else {
|
||||
if (ps->opts.vulkan) {
|
||||
mstring_append_fmt(preflight, "layout(binding = %d) ",
|
||||
ps->opts.tex_binding + i);
|
||||
}
|
||||
mstring_append_fmt(preflight, "uniform %s texSamp%d;\n",
|
||||
sampler_type, i);
|
||||
}
|
||||
mstring_append_fmt(preflight, "uniform %s texSamp%d;\n", sampler_type, i);
|
||||
|
||||
/* As this means a texture fetch does happen, do alphakill */
|
||||
if (ps->state->alphakill[i]) {
|
||||
|
||||
@@ -100,7 +100,10 @@ typedef struct GenPshGlslOptions {
|
||||
bool gles;
|
||||
int gles_version;
|
||||
int ubo_binding;
|
||||
int ubo_set;
|
||||
int tex_binding;
|
||||
bool bindless;
|
||||
int tex_push_offset;
|
||||
} GenPshGlslOptions;
|
||||
|
||||
MString *pgraph_glsl_gen_psh(const PshState *state, GenPshGlslOptions opts);
|
||||
|
||||
@@ -451,21 +451,37 @@ MString *pgraph_glsl_gen_vsh(const VshState *state, GenVshGlslOptions opts)
|
||||
opts.gles_version);
|
||||
|
||||
if (opts.vulkan) {
|
||||
// FIXME: Optimize uniforms
|
||||
if (num_uniform_attrs > 0 &&
|
||||
opts.use_push_constants_for_uniform_attrs) {
|
||||
mstring_append_fmt(output,
|
||||
"layout(push_constant) uniform PushConstants {\n"
|
||||
" vec4 inlineValue[%d];\n"
|
||||
"};\n\n",
|
||||
num_uniform_attrs);
|
||||
if (opts.vertex_push_offset > 0) {
|
||||
mstring_append_fmt(output,
|
||||
"layout(push_constant) uniform PushConstants {\n"
|
||||
" layout(offset = %d) vec4 inlineValue[%d];\n"
|
||||
"};\n\n",
|
||||
opts.vertex_push_offset, num_uniform_attrs);
|
||||
} else {
|
||||
mstring_append_fmt(output,
|
||||
"layout(push_constant) uniform PushConstants {\n"
|
||||
" vec4 inlineValue[%d];\n"
|
||||
"};\n\n",
|
||||
num_uniform_attrs);
|
||||
}
|
||||
}
|
||||
if (opts.ubo_set > 0) {
|
||||
mstring_append_fmt(
|
||||
output,
|
||||
"layout(set = %d, binding = %d, std140) uniform VshUniforms {\n"
|
||||
"%s"
|
||||
"};\n\n",
|
||||
opts.ubo_set, opts.ubo_binding, mstring_get_str(uniforms));
|
||||
} else {
|
||||
mstring_append_fmt(
|
||||
output,
|
||||
"layout(binding = %d, std140) uniform VshUniforms {\n"
|
||||
"%s"
|
||||
"};\n\n",
|
||||
opts.ubo_binding, mstring_get_str(uniforms));
|
||||
}
|
||||
mstring_append_fmt(
|
||||
output,
|
||||
"layout(binding = %d, std140) uniform VshUniforms {\n"
|
||||
"%s"
|
||||
"};\n\n",
|
||||
opts.ubo_binding, mstring_get_str(uniforms));
|
||||
} else {
|
||||
mstring_append(
|
||||
output, mstring_get_str(uniforms));
|
||||
|
||||
@@ -103,6 +103,8 @@ typedef struct GenVshGlslOptions {
|
||||
bool prefix_outputs;
|
||||
bool use_push_constants_for_uniform_attrs;
|
||||
int ubo_binding;
|
||||
int ubo_set;
|
||||
int vertex_push_offset;
|
||||
} GenVshGlslOptions;
|
||||
|
||||
MString *pgraph_glsl_gen_vsh(const VshState *state,
|
||||
|
||||
+117
-13
@@ -1107,26 +1107,60 @@ static void create_pipeline(PGRAPHState *pg)
|
||||
// }
|
||||
|
||||
|
||||
VkPushConstantRange push_constant_ranges[2];
|
||||
int num_push_constant_ranges = 0;
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &r->descriptor_set_layout,
|
||||
};
|
||||
|
||||
VkPushConstantRange push_constant_range;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
VkDescriptorSetLayout set_layouts[2];
|
||||
if (r->bindless_textures_supported) {
|
||||
set_layouts[0] = r->bindless_set_layout;
|
||||
set_layouts[1] = r->descriptor_set_layout;
|
||||
pipeline_layout_info.setLayoutCount = 2;
|
||||
pipeline_layout_info.pSetLayouts = set_layouts;
|
||||
push_constant_ranges[num_push_constant_ranges++] =
|
||||
(VkPushConstantRange){
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.offset = r->tex_push_offset,
|
||||
.size = NV2A_MAX_TEXTURES * sizeof(uint32_t),
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (r->use_push_constants_for_uniform_attrs) {
|
||||
int num_uniform_attributes =
|
||||
__builtin_popcount(r->shader_binding->state.vsh.uniform_attrs);
|
||||
if (num_uniform_attributes) {
|
||||
push_constant_range = (VkPushConstantRange){
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0,
|
||||
// FIXME: Minimize push constants
|
||||
.size = num_uniform_attributes * 4 * sizeof(float),
|
||||
};
|
||||
pipeline_layout_info.pushConstantRangeCount = 1;
|
||||
pipeline_layout_info.pPushConstantRanges = &push_constant_range;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported &&
|
||||
num_uniform_attributes > r->max_vertex_push_attrs) {
|
||||
num_uniform_attributes = 0;
|
||||
}
|
||||
#endif
|
||||
if (num_uniform_attributes) {
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
uint32_t vertex_push_offset =
|
||||
r->bindless_textures_supported && r->tex_push_offset == 0
|
||||
? NV2A_MAX_TEXTURES * sizeof(uint32_t)
|
||||
: 0;
|
||||
#else
|
||||
uint32_t vertex_push_offset = 0;
|
||||
#endif
|
||||
push_constant_ranges[num_push_constant_ranges++] =
|
||||
(VkPushConstantRange){
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = vertex_push_offset,
|
||||
.size = num_uniform_attributes * 4 * sizeof(float),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (num_push_constant_ranges > 0) {
|
||||
pipeline_layout_info.pushConstantRangeCount = num_push_constant_ranges;
|
||||
pipeline_layout_info.pPushConstantRanges = push_constant_ranges;
|
||||
}
|
||||
|
||||
VkPipelineLayout layout;
|
||||
@@ -1168,11 +1202,26 @@ static void create_pipeline(PGRAPHState *pg)
|
||||
NV2A_VK_DGROUP_END();
|
||||
}
|
||||
|
||||
static bool can_push_vertex_attr_values(PGRAPHVkState *r)
|
||||
{
|
||||
if (!r->use_push_constants_for_uniform_attrs) {
|
||||
return false;
|
||||
}
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported &&
|
||||
__builtin_popcount(r->shader_binding->state.vsh.uniform_attrs) >
|
||||
r->max_vertex_push_attrs) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static void push_vertex_attr_values(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->use_push_constants_for_uniform_attrs) {
|
||||
if (!can_push_vertex_attr_values(r)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1185,8 +1234,16 @@ static void push_vertex_attr_values(PGRAPHState *pg)
|
||||
values, &num_uniform_attrs);
|
||||
|
||||
if (num_uniform_attrs > 0) {
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
uint32_t vertex_push_offset =
|
||||
r->bindless_textures_supported && r->tex_push_offset == 0
|
||||
? NV2A_MAX_TEXTURES * sizeof(uint32_t)
|
||||
: 0;
|
||||
#else
|
||||
uint32_t vertex_push_offset = 0;
|
||||
#endif
|
||||
vkCmdPushConstants(r->command_buffer, r->pipeline_binding->layout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, vertex_push_offset,
|
||||
num_uniform_attrs * 4 * sizeof(float),
|
||||
&values);
|
||||
}
|
||||
@@ -1198,11 +1255,46 @@ static void bind_descriptor_sets(PGRAPHState *pg)
|
||||
assert(r->descriptor_set_index >= 1);
|
||||
|
||||
vkCmdBindDescriptorSets(r->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
r->pipeline_binding->layout, 0, 1,
|
||||
r->pipeline_binding->layout,
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
r->bindless_textures_supported ? 1 : 0,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
1,
|
||||
&r->descriptor_sets[r->descriptor_set_index - 1], 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
static void bind_bindless_set(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets(r->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
r->pipeline_binding->layout, 0, 1,
|
||||
&r->bindless_descriptor_set, 0, NULL);
|
||||
}
|
||||
|
||||
static void push_texture_indices(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
vkCmdPushConstants(r->command_buffer, r->pipeline_binding->layout,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, r->tex_push_offset,
|
||||
sizeof(r->tex_bindless_indices),
|
||||
r->tex_bindless_indices);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void begin_query(PGRAPHVkState *r)
|
||||
{
|
||||
assert(r->in_command_buffer);
|
||||
@@ -1490,6 +1582,9 @@ void pgraph_vk_begin_command_buffer(PGRAPHState *pg)
|
||||
&command_buffer_begin_info));
|
||||
r->command_buffer_start_time = pg->draw_time;
|
||||
r->in_command_buffer = true;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
r->bindless_set_bound = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// FIXME: Refactor below
|
||||
@@ -1699,8 +1794,17 @@ static void begin_draw(PGRAPHState *pg)
|
||||
}
|
||||
|
||||
if (!pg->clearing && !r->pre_draw_skipped) {
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported && !r->bindless_set_bound) {
|
||||
bind_bindless_set(pg);
|
||||
r->bindless_set_bound = true;
|
||||
}
|
||||
#endif
|
||||
bind_descriptor_sets(pg);
|
||||
push_vertex_attr_values(pg);
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
push_texture_indices(pg);
|
||||
#endif
|
||||
}
|
||||
|
||||
r->in_draw = true;
|
||||
|
||||
@@ -366,6 +366,16 @@ static void add_optional_device_extension_names(
|
||||
r->memory_budget_extension_enabled = add_extension_if_available(
|
||||
available_extensions, enabled_extension_names,
|
||||
VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->device_props.apiVersion >= VK_API_VERSION_1_2) {
|
||||
r->bindless_textures_supported = true;
|
||||
} else {
|
||||
r->bindless_textures_supported = add_extension_if_available(
|
||||
available_extensions, enabled_extension_names,
|
||||
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool check_device_support_required_extensions(VkPhysicalDevice device)
|
||||
@@ -1051,6 +1061,82 @@ static bool create_logical_device(PGRAPHState *pg, Error **errp)
|
||||
|
||||
void *next_struct = NULL;
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features;
|
||||
if (r->bindless_textures_supported) {
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_query = {
|
||||
.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
|
||||
};
|
||||
VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props = {
|
||||
.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
|
||||
};
|
||||
VkPhysicalDeviceFeatures2 features2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &descriptor_indexing_query,
|
||||
};
|
||||
VkPhysicalDeviceProperties2 props2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
.pNext = &descriptor_indexing_props,
|
||||
};
|
||||
|
||||
vkGetPhysicalDeviceFeatures2(r->physical_device, &features2);
|
||||
vkGetPhysicalDeviceProperties2(r->physical_device, &props2);
|
||||
|
||||
bool have_all =
|
||||
descriptor_indexing_query.descriptorBindingPartiallyBound &&
|
||||
descriptor_indexing_query
|
||||
.descriptorBindingSampledImageUpdateAfterBind &&
|
||||
descriptor_indexing_props
|
||||
.maxPerStageDescriptorUpdateAfterBindSampledImages >=
|
||||
MAX_BINDLESS_TEXTURES;
|
||||
|
||||
if (have_all) {
|
||||
memset(&descriptor_indexing_features, 0,
|
||||
sizeof(descriptor_indexing_features));
|
||||
descriptor_indexing_features.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
|
||||
descriptor_indexing_features.descriptorBindingPartiallyBound =
|
||||
VK_TRUE;
|
||||
descriptor_indexing_features
|
||||
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE;
|
||||
descriptor_indexing_features.pNext = next_struct;
|
||||
next_struct = &descriptor_indexing_features;
|
||||
|
||||
if (r->device_props.limits.maxPushConstantsSize >=
|
||||
NV2A_VERTEXSHADER_ATTRIBUTES * 4 * sizeof(float) +
|
||||
NV2A_MAX_TEXTURES * sizeof(uint32_t)) {
|
||||
r->tex_push_offset =
|
||||
NV2A_VERTEXSHADER_ATTRIBUTES * 4 * sizeof(float);
|
||||
r->max_vertex_push_attrs = NV2A_VERTEXSHADER_ATTRIBUTES;
|
||||
} else {
|
||||
r->tex_push_offset = 0;
|
||||
r->max_vertex_push_attrs =
|
||||
NV2A_VERTEXSHADER_ATTRIBUTES - 1;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Bindless textures enabled (push offset=%u, "
|
||||
"max vertex attrs=%d, max samplers=%u)\n",
|
||||
r->tex_push_offset, r->max_vertex_push_attrs,
|
||||
descriptor_indexing_props
|
||||
.maxPerStageDescriptorUpdateAfterBindSampledImages);
|
||||
} else {
|
||||
r->bindless_textures_supported = false;
|
||||
fprintf(stderr,
|
||||
"Bindless textures disabled (partiallyBound=%d, "
|
||||
"updateAfterBind=%d, maxSamplers=%u)\n",
|
||||
descriptor_indexing_query
|
||||
.descriptorBindingPartiallyBound,
|
||||
descriptor_indexing_query
|
||||
.descriptorBindingSampledImageUpdateAfterBind,
|
||||
descriptor_indexing_props
|
||||
.maxPerStageDescriptorUpdateAfterBindSampledImages);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border_features;
|
||||
if (r->custom_border_color_extension_enabled) {
|
||||
custom_border_features = (VkPhysicalDeviceCustomBorderColorFeaturesEXT){
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#define NUM_GFX_DESCRIPTOR_SETS 8192
|
||||
#define MAX_FRAMEBUFFERS 256
|
||||
#define FB_CACHE_MAX 32
|
||||
#define OPT_BINDLESS_TEXTURES 1
|
||||
#define MAX_BINDLESS_TEXTURES 1024
|
||||
#define BINDLESS_STAGE_SLOT_BASE (MAX_BINDLESS_TEXTURES - NV2A_MAX_TEXTURES)
|
||||
|
||||
typedef struct QueueFamilyIndices {
|
||||
int queue_family;
|
||||
@@ -247,6 +250,10 @@ typedef struct TextureBinding {
|
||||
uint32_t submit_time;
|
||||
unsigned int dirty_check_frame;
|
||||
bool dirty_check_result;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
uint32_t bindless_slot;
|
||||
uint32_t bindless_binding;
|
||||
#endif
|
||||
} TextureBinding;
|
||||
|
||||
typedef struct QueryReport {
|
||||
@@ -366,6 +373,11 @@ typedef struct PGRAPHVkState {
|
||||
bool debug_utils_extension_enabled;
|
||||
bool custom_border_color_extension_enabled;
|
||||
bool memory_budget_extension_enabled;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
bool bindless_textures_supported;
|
||||
uint32_t tex_push_offset;
|
||||
int max_vertex_push_attrs;
|
||||
#endif
|
||||
|
||||
VkPhysicalDevice physical_device;
|
||||
VkPhysicalDeviceFeatures enabled_physical_device_features;
|
||||
@@ -383,6 +395,9 @@ typedef struct PGRAPHVkState {
|
||||
VkFence command_buffer_fence;
|
||||
unsigned int command_buffer_start_time;
|
||||
bool in_command_buffer;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
bool bindless_set_bound;
|
||||
#endif
|
||||
uint32_t submit_count;
|
||||
|
||||
VkCommandBuffer aux_command_buffer;
|
||||
@@ -419,6 +434,13 @@ typedef struct PGRAPHVkState {
|
||||
VkDescriptorSet *descriptor_sets;
|
||||
int descriptor_set_count;
|
||||
int descriptor_set_index;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
VkDescriptorPool bindless_descriptor_pool;
|
||||
VkDescriptorSetLayout bindless_set_layout;
|
||||
VkDescriptorSet bindless_descriptor_set;
|
||||
uint64_t bindless_slot_bitmap[MAX_BINDLESS_TEXTURES / 64];
|
||||
uint32_t tex_bindless_indices[NV2A_MAX_TEXTURES];
|
||||
#endif
|
||||
|
||||
StorageBuffer storage_buffers[BUFFER_COUNT];
|
||||
PrimRewriteBuf prim_rewrite_buf;
|
||||
|
||||
@@ -34,6 +34,28 @@ static void create_descriptor_pool(PGRAPHState *pg)
|
||||
|
||||
size_t num_sets = r->descriptor_set_count;
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
VkDescriptorPoolSize pool_sizes[] = {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 2 * num_sets,
|
||||
},
|
||||
};
|
||||
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.poolSizeCount = ARRAY_SIZE(pool_sizes),
|
||||
.pPoolSizes = pool_sizes,
|
||||
.maxSets = num_sets,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorPool(r->device, &pool_info, NULL,
|
||||
&r->descriptor_pool));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
VkDescriptorPoolSize pool_sizes[] = {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
@@ -68,6 +90,33 @@ static void create_descriptor_set_layout(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
VkDescriptorSetLayoutBinding bindings[2] = {
|
||||
{
|
||||
.binding = VSH_UBO_BINDING,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
},
|
||||
{
|
||||
.binding = PSH_UBO_BINDING,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
},
|
||||
};
|
||||
VkDescriptorSetLayoutCreateInfo layout_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = ARRAY_SIZE(bindings),
|
||||
.pBindings = bindings,
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(r->device, &layout_info, NULL,
|
||||
&r->descriptor_set_layout));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
VkDescriptorSetLayoutBinding bindings[2 + NV2A_MAX_TEXTURES];
|
||||
|
||||
bindings[0] = (VkDescriptorSetLayoutBinding){
|
||||
@@ -145,6 +194,109 @@ static void destroy_descriptor_sets(PGRAPHState *pg)
|
||||
r->descriptor_sets = NULL;
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
static void create_bindless_descriptor_resources(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutBinding bindings[3];
|
||||
VkDescriptorBindingFlags binding_flags[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bindings[i] = (VkDescriptorSetLayoutBinding){
|
||||
.binding = (uint32_t)i,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = MAX_BINDLESS_TEXTURES,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
};
|
||||
binding_flags[i] =
|
||||
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT |
|
||||
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo flags_info = {
|
||||
.sType =
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
|
||||
.bindingCount = ARRAY_SIZE(binding_flags),
|
||||
.pBindingFlags = binding_flags,
|
||||
};
|
||||
VkDescriptorSetLayoutCreateInfo layout_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = &flags_info,
|
||||
.flags =
|
||||
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
|
||||
.bindingCount = ARRAY_SIZE(bindings),
|
||||
.pBindings = bindings,
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(r->device, &layout_info, NULL,
|
||||
&r->bindless_set_layout));
|
||||
|
||||
VkDescriptorPoolSize pool_size = {
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 3 * MAX_BINDLESS_TEXTURES,
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
|
||||
.maxSets = 1,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &pool_size,
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorPool(r->device, &pool_info, NULL,
|
||||
&r->bindless_descriptor_pool));
|
||||
|
||||
VkDescriptorSetAllocateInfo alloc_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = r->bindless_descriptor_pool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &r->bindless_set_layout,
|
||||
};
|
||||
VK_CHECK(vkAllocateDescriptorSets(r->device, &alloc_info,
|
||||
&r->bindless_descriptor_set));
|
||||
|
||||
memset(r->bindless_slot_bitmap, 0, sizeof(r->bindless_slot_bitmap));
|
||||
memset(r->tex_bindless_indices, 0, sizeof(r->tex_bindless_indices));
|
||||
r->bindless_slot_bitmap[0] |= 1ULL;
|
||||
for (uint32_t slot = BINDLESS_STAGE_SLOT_BASE;
|
||||
slot < MAX_BINDLESS_TEXTURES; slot++) {
|
||||
r->bindless_slot_bitmap[slot / 64] |= (1ULL << (slot % 64));
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_bindless_descriptor_resources(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
vkDestroyDescriptorPool(r->device, r->bindless_descriptor_pool, NULL);
|
||||
vkDestroyDescriptorSetLayout(r->device, r->bindless_set_layout, NULL);
|
||||
r->bindless_descriptor_pool = VK_NULL_HANDLE;
|
||||
r->bindless_set_layout = VK_NULL_HANDLE;
|
||||
r->bindless_descriptor_set = VK_NULL_HANDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool can_use_vertex_push_constants(PGRAPHVkState *r,
|
||||
const VshState *state)
|
||||
{
|
||||
if (!r->use_push_constants_for_uniform_attrs) {
|
||||
return false;
|
||||
}
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported &&
|
||||
__builtin_popcount(state->uniform_attrs) > r->max_vertex_push_attrs) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void pgraph_vk_update_descriptor_sets(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
@@ -153,7 +305,12 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg)
|
||||
r->uniforms_changed ||
|
||||
!r->storage_buffers[BUFFER_UNIFORM_STAGING].buffer_offset;
|
||||
|
||||
if (!(r->shader_bindings_changed || r->texture_bindings_changed ||
|
||||
if (!(r->shader_bindings_changed ||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
(!r->bindless_textures_supported && r->texture_bindings_changed) ||
|
||||
#else
|
||||
r->texture_bindings_changed ||
|
||||
#endif
|
||||
(r->descriptor_set_index == 0) || need_uniform_write)) {
|
||||
return; // Nothing changed
|
||||
}
|
||||
@@ -179,8 +336,6 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg)
|
||||
need_uniform_write = true;
|
||||
}
|
||||
|
||||
VkWriteDescriptorSet descriptor_writes[2 + NV2A_MAX_TEXTURES];
|
||||
|
||||
assert(r->descriptor_set_index < r->descriptor_set_count);
|
||||
|
||||
if (need_uniform_write) {
|
||||
@@ -196,6 +351,7 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg)
|
||||
}
|
||||
|
||||
VkDescriptorBufferInfo ubo_buffer_infos[2];
|
||||
VkWriteDescriptorSet descriptor_writes[2 + NV2A_MAX_TEXTURES];
|
||||
for (int i = 0; i < ARRAY_SIZE(layouts); i++) {
|
||||
ubo_buffer_infos[i] = (VkDescriptorBufferInfo){
|
||||
.buffer = r->storage_buffers[BUFFER_UNIFORM].buffer,
|
||||
@@ -213,29 +369,37 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg)
|
||||
};
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo image_infos[NV2A_MAX_TEXTURES];
|
||||
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||
image_infos[i] = (VkDescriptorImageInfo){
|
||||
.imageLayout = r->tex_surface_direct[i]
|
||||
? r->tex_surface_direct_layout[i]
|
||||
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.imageView = r->tex_surface_direct[i]
|
||||
? r->tex_surface_direct_views[i]
|
||||
: r->texture_bindings[i]->image_view,
|
||||
.sampler = r->texture_bindings[i]->sampler,
|
||||
};
|
||||
descriptor_writes[2 + i] = (VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = r->descriptor_sets[r->descriptor_set_index],
|
||||
.dstBinding = PSH_TEX_BINDING + i,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.pImageInfo = &image_infos[i],
|
||||
};
|
||||
}
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
vkUpdateDescriptorSets(r->device, 2, descriptor_writes, 0, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
VkDescriptorImageInfo image_infos[NV2A_MAX_TEXTURES];
|
||||
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||
image_infos[i] = (VkDescriptorImageInfo){
|
||||
.imageLayout = r->tex_surface_direct[i]
|
||||
? r->tex_surface_direct_layout[i]
|
||||
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.imageView = r->tex_surface_direct[i]
|
||||
? r->tex_surface_direct_views[i]
|
||||
: r->texture_bindings[i]->image_view,
|
||||
.sampler = r->texture_bindings[i]->sampler,
|
||||
};
|
||||
descriptor_writes[2 + i] = (VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = r->descriptor_sets[r->descriptor_set_index],
|
||||
.dstBinding = PSH_TEX_BINDING + i,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.pImageInfo = &image_infos[i],
|
||||
};
|
||||
}
|
||||
|
||||
vkUpdateDescriptorSets(r->device, 6, descriptor_writes, 0, NULL);
|
||||
vkUpdateDescriptorSets(r->device, 2 + NV2A_MAX_TEXTURES,
|
||||
descriptor_writes, 0, NULL);
|
||||
}
|
||||
|
||||
r->descriptor_set_index++;
|
||||
}
|
||||
@@ -293,8 +457,18 @@ static void shader_cache_entry_init(Lru *lru, LruNode *node, const void *state)
|
||||
key.vsh.glsl_opts.vulkan = true;
|
||||
key.vsh.glsl_opts.prefix_outputs = need_geometry_shader;
|
||||
key.vsh.glsl_opts.use_push_constants_for_uniform_attrs =
|
||||
r->use_push_constants_for_uniform_attrs;
|
||||
can_use_vertex_push_constants(r, &binding->state.vsh);
|
||||
key.vsh.glsl_opts.ubo_binding = VSH_UBO_BINDING;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
key.vsh.glsl_opts.ubo_set = 1;
|
||||
if (key.vsh.glsl_opts.use_push_constants_for_uniform_attrs &&
|
||||
r->tex_push_offset == 0) {
|
||||
key.vsh.glsl_opts.vertex_push_offset =
|
||||
NV2A_MAX_TEXTURES * sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
binding->vsh.module_info = get_and_ref_shader_module_for_key(r, &key);
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
@@ -302,7 +476,16 @@ static void shader_cache_entry_init(Lru *lru, LruNode *node, const void *state)
|
||||
key.psh.state = binding->state.psh;
|
||||
key.psh.glsl_opts.vulkan = true;
|
||||
key.psh.glsl_opts.ubo_binding = PSH_UBO_BINDING;
|
||||
key.psh.glsl_opts.tex_binding = PSH_TEX_BINDING;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
key.psh.glsl_opts.ubo_set = 1;
|
||||
key.psh.glsl_opts.bindless = true;
|
||||
key.psh.glsl_opts.tex_push_offset = r->tex_push_offset;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
key.psh.glsl_opts.tex_binding = PSH_TEX_BINDING;
|
||||
}
|
||||
binding->psh.module_info = get_and_ref_shader_module_for_key(r, &key);
|
||||
|
||||
update_shader_uniform_locs(binding);
|
||||
@@ -548,16 +731,32 @@ void pgraph_vk_init_shaders(PGRAPHState *pg)
|
||||
create_descriptor_pool(pg);
|
||||
create_descriptor_set_layout(pg);
|
||||
create_descriptor_sets(pg);
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
create_bindless_descriptor_resources(pg);
|
||||
#endif
|
||||
shader_cache_init(pg);
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
size_t vtx_budget = r->max_vertex_push_attrs * 4 * sizeof(float);
|
||||
r->use_push_constants_for_uniform_attrs =
|
||||
(r->device_props.limits.maxPushConstantsSize >=
|
||||
vtx_budget + NV2A_MAX_TEXTURES * sizeof(uint32_t));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
r->use_push_constants_for_uniform_attrs =
|
||||
(r->device_props.limits.maxPushConstantsSize >=
|
||||
MAX_UNIFORM_ATTR_VALUES_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void pgraph_vk_finalize_shaders(PGRAPHState *pg)
|
||||
{
|
||||
shader_cache_finalize(pg);
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
destroy_bindless_descriptor_resources(pg);
|
||||
#endif
|
||||
destroy_descriptor_sets(pg);
|
||||
destroy_descriptor_set_layout(pg);
|
||||
destroy_descriptor_pool(pg);
|
||||
|
||||
@@ -1308,6 +1308,17 @@ static bool check_surface_to_texture_compatiblity(const SurfaceBinding *surface,
|
||||
surface->host_fmt.host_bytes_per_pixel == vk_format_texel_size(tex_vkf.vk_format);
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
static void update_bindless_texture_descriptor(PGRAPHVkState *r,
|
||||
uint32_t binding,
|
||||
uint32_t slot,
|
||||
VkImageView image_view,
|
||||
VkImageLayout image_layout,
|
||||
VkSampler sampler);
|
||||
static void set_texture_bindless_index(PGRAPHState *pg, int texture_idx,
|
||||
TextureBinding *binding);
|
||||
#endif
|
||||
|
||||
static void create_dummy_texture(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
@@ -1433,7 +1444,17 @@ static void create_dummy_texture(PGRAPHState *pg)
|
||||
.allocation = texture_allocation,
|
||||
.image_view = texture_image_view,
|
||||
.sampler = texture_sampler,
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
.bindless_slot = 0,
|
||||
.bindless_binding = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
update_bindless_texture_descriptor(
|
||||
r, 0, 0, texture_image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
texture_sampler);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void destroy_dummy_texture(PGRAPHVkState *r)
|
||||
@@ -1441,6 +1462,60 @@ static void destroy_dummy_texture(PGRAPHVkState *r)
|
||||
texture_cache_release_node_resources(r, &r->dummy_texture);
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
static void update_bindless_texture_descriptor(PGRAPHVkState *r,
|
||||
uint32_t binding,
|
||||
uint32_t slot,
|
||||
VkImageView image_view,
|
||||
VkImageLayout image_layout,
|
||||
VkSampler sampler)
|
||||
{
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo image_info = {
|
||||
.imageLayout = image_layout,
|
||||
.imageView = image_view,
|
||||
.sampler = sampler,
|
||||
};
|
||||
VkWriteDescriptorSet write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = r->bindless_descriptor_set,
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = slot,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.pImageInfo = &image_info,
|
||||
};
|
||||
vkUpdateDescriptorSets(r->device, 1, &write, 0, NULL);
|
||||
}
|
||||
|
||||
static void set_texture_bindless_index(PGRAPHState *pg, int texture_idx,
|
||||
TextureBinding *binding)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
uint32_t slot = 0;
|
||||
|
||||
if (!r->bindless_textures_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (binding != NULL) {
|
||||
slot = binding->bindless_slot;
|
||||
if (r->tex_surface_direct[texture_idx]) {
|
||||
slot = BINDLESS_STAGE_SLOT_BASE + texture_idx;
|
||||
update_bindless_texture_descriptor(
|
||||
r, binding->bindless_binding, slot,
|
||||
r->tex_surface_direct_views[texture_idx],
|
||||
r->tex_surface_direct_layout[texture_idx], binding->sampler);
|
||||
}
|
||||
}
|
||||
|
||||
r->tex_bindless_indices[texture_idx] = slot;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_texture_label(PGRAPHState *pg, TextureBinding *texture)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
@@ -1655,6 +1730,9 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
|
||||
}
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
set_texture_bindless_index(pg, texture_idx, snode);
|
||||
#endif
|
||||
NV2A_VK_DGROUP_END();
|
||||
return;
|
||||
}
|
||||
@@ -1852,6 +1930,22 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
|
||||
|
||||
set_texture_label(pg, snode);
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported) {
|
||||
if (state.cubemap) {
|
||||
snode->bindless_binding = 2;
|
||||
} else if (state.dimensionality == 3) {
|
||||
snode->bindless_binding = 1;
|
||||
} else {
|
||||
snode->bindless_binding = 0;
|
||||
}
|
||||
update_bindless_texture_descriptor(
|
||||
r, snode->bindless_binding, snode->bindless_slot,
|
||||
snode->image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
snode->sampler);
|
||||
}
|
||||
#endif
|
||||
|
||||
r->texture_bindings[texture_idx] = snode;
|
||||
|
||||
if (surface_to_texture) {
|
||||
@@ -1878,6 +1972,9 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
|
||||
snode->draw_time = 0;
|
||||
}
|
||||
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
set_texture_bindless_index(pg, texture_idx, snode);
|
||||
#endif
|
||||
NV2A_VK_DGROUP_END();
|
||||
}
|
||||
|
||||
@@ -1973,6 +2070,9 @@ void pgraph_vk_bind_textures(NV2AState *d)
|
||||
r->tex_surface_direct_layout[i] =
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
pg->texture_dirty[i] = false;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
r->tex_bindless_indices[i] = 0;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2004,6 +2104,7 @@ void pgraph_vk_bind_textures(NV2AState *d)
|
||||
|
||||
static void texture_cache_entry_init(Lru *lru, LruNode *node, const void *state)
|
||||
{
|
||||
PGRAPHVkState *r = container_of(lru, PGRAPHVkState, texture_cache);
|
||||
TextureBinding *snode = container_of(node, TextureBinding, node);
|
||||
|
||||
snode->image = VK_NULL_HANDLE;
|
||||
@@ -2015,6 +2116,27 @@ static void texture_cache_entry_init(Lru *lru, LruNode *node, const void *state)
|
||||
snode->submit_time = 0;
|
||||
snode->dirty_check_frame = 0;
|
||||
snode->dirty_check_result = false;
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
snode->bindless_slot = 0;
|
||||
snode->bindless_binding = 0;
|
||||
if (r->bindless_textures_supported) {
|
||||
for (uint32_t word = 0;
|
||||
word < ARRAY_SIZE(r->bindless_slot_bitmap); word++) {
|
||||
if (r->bindless_slot_bitmap[word] == UINT64_MAX) {
|
||||
continue;
|
||||
}
|
||||
uint32_t bit = __builtin_ctzll(~r->bindless_slot_bitmap[word]);
|
||||
uint32_t slot = word * 64 + bit;
|
||||
if (slot >= BINDLESS_STAGE_SLOT_BASE) {
|
||||
break;
|
||||
}
|
||||
snode->bindless_slot = slot;
|
||||
r->bindless_slot_bitmap[word] |= (1ULL << bit);
|
||||
break;
|
||||
}
|
||||
assert(snode->bindless_slot > 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void texture_cache_release_node_resources(PGRAPHVkState *r, TextureBinding *snode)
|
||||
@@ -2061,6 +2183,13 @@ static void texture_cache_entry_post_evict(Lru *lru, LruNode *node)
|
||||
{
|
||||
PGRAPHVkState *r = container_of(lru, PGRAPHVkState, texture_cache);
|
||||
TextureBinding *snode = container_of(node, TextureBinding, node);
|
||||
#if OPT_BINDLESS_TEXTURES
|
||||
if (r->bindless_textures_supported && snode->bindless_slot > 0 &&
|
||||
snode->bindless_slot < BINDLESS_STAGE_SLOT_BASE) {
|
||||
r->bindless_slot_bitmap[snode->bindless_slot / 64] &=
|
||||
~(1ULL << (snode->bindless_slot % 64));
|
||||
}
|
||||
#endif
|
||||
texture_cache_release_node_resources(r, snode);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user