mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-13 09:38:14 +03:00
NVENC: Handle color conversion by ourself on GPU
This commit is contained in:
@@ -11,12 +11,39 @@
|
||||
|
||||
enum shader_dev_sub_enum {
|
||||
SHADER_DEV_SUB_SHADER_FFP = 0,
|
||||
SHADER_DEV_SUB_CONVERT_YCBCR_BT709,
|
||||
SHADER_DEV_SUB_CONVERT_RGB,
|
||||
SHADER_DEV_SUB_CONVERT_ALPHA,
|
||||
#if DISPLAY_IBL
|
||||
SHADER_DEV_SUB_CUBEMAP_DISPLAY,
|
||||
#endif
|
||||
SHADER_DEV_SUB_SHADER_END,
|
||||
};
|
||||
|
||||
static const int32_t convert_ycbcr_bt709_vpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int32_t convert_ycbcr_bt709_fpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int32_t convert_alpha_vpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int32_t convert_alpha_fpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int32_t convert_rgb_vpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int32_t convert_rgb_fpt_unival_max[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
#if DISPLAY_IBL
|
||||
static const int32_t cubemap_display_vpt_unival_max[] = {
|
||||
-1,
|
||||
@@ -44,6 +71,39 @@ static const int32_t cubemap_display_fpt_unival_max[] = {
|
||||
#define SHADER_DESCRIPTION_COMMON_QUAD \
|
||||
{ SHADER_DESCRIPTION_UNIFORM, 0, sizeof(quad_shader_data), U_INVALID, }
|
||||
|
||||
static const shader_description convert_ycbcr_bt709_vpt_desc[] = {
|
||||
SHADER_DESCRIPTION_COMMON_QUAD,
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
static const shader_description convert_ycbcr_bt709_fpt_desc[] = {
|
||||
{ SHADER_DESCRIPTION_SAMPLER, 0, 0, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_FRAGMENT_OUTPUT, 0, 4, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
static const shader_description convert_alpha_vpt_desc[] = {
|
||||
SHADER_DESCRIPTION_COMMON_QUAD,
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
static const shader_description convert_alpha_fpt_desc[] = {
|
||||
{ SHADER_DESCRIPTION_SAMPLER, 0, 0, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_FRAGMENT_OUTPUT, 0, 4, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
static const shader_description convert_rgb_vpt_desc[] = {
|
||||
SHADER_DESCRIPTION_COMMON_QUAD,
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
static const shader_description convert_rgb_fpt_desc[] = {
|
||||
{ SHADER_DESCRIPTION_SAMPLER, 0, 0, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_FRAGMENT_OUTPUT, 0, 4, U_INVALID, },
|
||||
{ SHADER_DESCRIPTION_END, -1, -1, U_INVALID, },
|
||||
};
|
||||
|
||||
#if DISPLAY_IBL
|
||||
static const shader_description cubemap_display_vpt_desc[] = {
|
||||
{ SHADER_DESCRIPTION_VERTEX_INPUT, 0, 3, U_INVALID, },
|
||||
@@ -65,6 +125,18 @@ static const shader_description cubemap_display_fpt_desc[] = {
|
||||
#undef SHADER_DESCRIPTION_EFFECT_TEXTURE_SAMPLER
|
||||
#pragma endregion
|
||||
|
||||
static const uniform_name CONVERT_YCBCR_BT709_uniform[] = {
|
||||
U_INVALID,
|
||||
};
|
||||
|
||||
static const uniform_name CONVERT_ALPHA_uniform[] = {
|
||||
U_INVALID,
|
||||
};
|
||||
|
||||
static const uniform_name CONVERT_RGB_uniform[] = {
|
||||
U_INVALID,
|
||||
};
|
||||
|
||||
#if DISPLAY_IBL
|
||||
static const uniform_name CUBEMAP_DISPLAY_uniform[] = {
|
||||
U_INVALID,
|
||||
@@ -82,6 +154,21 @@ static const uniform_name CUBEMAP_DISPLAY_uniform[] = {
|
||||
fp##_fpt_desc, \
|
||||
}
|
||||
|
||||
static const shader_sub_table CONVERT_YCBCR_BT709_table[] = {
|
||||
shader_sub_table_struct(CONVERT_YCBCR_BT709,
|
||||
convert_ycbcr_bt709, convert_ycbcr_bt709),
|
||||
};
|
||||
|
||||
static const shader_sub_table CONVERT_ALPHA_table[] = {
|
||||
shader_sub_table_struct(CONVERT_ALPHA,
|
||||
convert_alpha, convert_alpha),
|
||||
};
|
||||
|
||||
static const shader_sub_table CONVERT_RGB_table[] = {
|
||||
shader_sub_table_struct(CONVERT_RGB,
|
||||
convert_rgb, convert_rgb),
|
||||
};
|
||||
|
||||
#if DISPLAY_IBL
|
||||
static const shader_sub_table CUBEMAP_DISPLAY_table[] = {
|
||||
shader_sub_table_struct(CUBEMAP_DISPLAY,
|
||||
@@ -110,6 +197,9 @@ const shader_table shader_dev_table[] = {
|
||||
0,
|
||||
0,
|
||||
},
|
||||
shader_table_struct(CONVERT_YCBCR_BT709),
|
||||
shader_table_struct(CONVERT_ALPHA),
|
||||
shader_table_struct(CONVERT_RGB),
|
||||
#if DISPLAY_IBL
|
||||
shader_table_struct(CUBEMAP_DISPLAY),
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
enum shader_dev_enum {
|
||||
SHADER_DEV_FFP = 0,
|
||||
SHADER_DEV_CONVERT_YCBCR_BT709,
|
||||
SHADER_DEV_CONVERT_ALPHA,
|
||||
SHADER_DEV_CONVERT_RGB,
|
||||
SHADER_DEV_CONVERT_YCGCO,
|
||||
#if DISPLAY_IBL
|
||||
SHADER_DEV_CUBEMAP_DISPLAY,
|
||||
#endif
|
||||
|
||||
@@ -85,7 +85,9 @@ nvenc_encoder::nvenc_encoder(int32_t width, int32_t height,
|
||||
is_10_bit &= support_10bit_encode;
|
||||
is_444 &= support_yuv444_encode;
|
||||
|
||||
buffer_format = is_rgb ? NV_ENC_BUFFER_FORMAT_AYUV : NV_ENC_BUFFER_FORMAT_ARGB;
|
||||
is_10_bit &= !lossless;
|
||||
|
||||
buffer_format = NV_ENC_BUFFER_FORMAT_ARGB;
|
||||
|
||||
num_bframes = clamp_def(num_bframes, 0, num_max_bframes);
|
||||
extra_output_delay = max_def(extra_output_delay, 2);
|
||||
@@ -128,7 +130,7 @@ nvenc_encoder::nvenc_encoder(int32_t width, int32_t height,
|
||||
if (!lossless)
|
||||
hevc_config.useBFramesAsRef = (NV_ENC_BFRAME_REF_MODE)(support_bframe_ref_mode & NV_ENC_BFRAME_REF_MODE_MIDDLE);
|
||||
hevc_config.outputBitDepth = is_10_bit ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
|
||||
hevc_config.inputBitDepth = is_10_bit ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
|
||||
hevc_config.inputBitDepth = NV_ENC_BIT_DEPTH_8;
|
||||
hevc_config.hevcVUIParameters.videoSignalTypePresentFlag = 1;
|
||||
hevc_config.hevcVUIParameters.videoFormat = NV_ENC_VUI_VIDEO_FORMAT_UNSPECIFIED;
|
||||
hevc_config.hevcVUIParameters.videoFullRangeFlag = 1;
|
||||
@@ -181,7 +183,7 @@ nvenc_encoder::nvenc_encoder(int32_t width, int32_t height,
|
||||
tex_desc.Height = height;
|
||||
tex_desc.MipLevels = 1;
|
||||
tex_desc.ArraySize = 1;
|
||||
tex_desc.Format = is_rgb ? DXGI_FORMAT_AYUV : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
tex_desc.Format = DXGI_FORMAT_AYUV;
|
||||
tex_desc.SampleDesc.Count = 1;
|
||||
tex_desc.SampleDesc.Quality = 0;
|
||||
tex_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
+117
-131
@@ -6287,15 +6287,23 @@ struct d3d_gl_fbo_tex_struct {
|
||||
GLuint tex;
|
||||
HANDLE handle;
|
||||
|
||||
inline d3d_gl_fbo_tex_struct() : tex(), handle() {
|
||||
inline d3d_gl_fbo_tex_struct() : fbo(), tex(), handle() {
|
||||
|
||||
}
|
||||
|
||||
inline void init(ID3D11Texture2D* texture) {
|
||||
inline void init(ID3D11Texture2D* texture = 0) {
|
||||
glGenTextures(1, &tex);
|
||||
|
||||
handle = wglDXRegisterObjectNV(d3d_gl_handle, texture,
|
||||
tex, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
|
||||
if (GLAD_WGL_NV_DX_interop2)
|
||||
handle = wglDXRegisterObjectNV(d3d_gl_handle, texture,
|
||||
tex, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
|
||||
else {
|
||||
gl_state_bind_texture_2d(tex);
|
||||
::texture* tex = rctx_ptr->screen_buffer.color_texture;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
|
||||
tex->width, tex->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
gl_state_bind_texture_2d(0);
|
||||
}
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
|
||||
@@ -6310,19 +6318,23 @@ struct d3d_gl_fbo_tex_struct {
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
fbo = 0;
|
||||
|
||||
wglDXUnregisterObjectNV(d3d_gl_handle, handle);
|
||||
handle = 0;
|
||||
if (GLAD_WGL_NV_DX_interop2 && handle) {
|
||||
wglDXUnregisterObjectNV(d3d_gl_handle, handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &tex);
|
||||
tex = 0;
|
||||
}
|
||||
|
||||
inline void lock() {
|
||||
wglDXLockObjectsNV(d3d_gl_handle, 1, &handle);
|
||||
if (GLAD_WGL_NV_DX_interop2 && handle)
|
||||
wglDXLockObjectsNV(d3d_gl_handle, 1, &handle);
|
||||
}
|
||||
|
||||
inline void unlock() {
|
||||
wglDXUnlockObjectsNV(d3d_gl_handle, 1, &handle);
|
||||
if (GLAD_WGL_NV_DX_interop2 && handle)
|
||||
wglDXUnlockObjectsNV(d3d_gl_handle, 1, &handle);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6339,8 +6351,8 @@ waitable_timer d3d_timer;
|
||||
static const size_t nvenc_src_pixel_size = 4;
|
||||
static const size_t nvenc_dst_pixel_size = 4;
|
||||
|
||||
static nvenc_encoder_format nvenc_format;
|
||||
static bool nvenc_lossless;
|
||||
static nvenc_encoder_format nvenc_format = NVENC_ENCODER_YUV420_10BIT;
|
||||
static bool nvenc_lossless = false;
|
||||
|
||||
static bool nvenc_rgb;
|
||||
|
||||
@@ -6393,64 +6405,71 @@ bool x_pv_game::ctrl() {
|
||||
#if BAKE_PNG || BAKE_VIDEO
|
||||
if (img_write && frame_prev != x_pv_game_ptr->frame) {
|
||||
texture* tex = rctx_ptr->screen_buffer.color_texture;
|
||||
int32_t width = tex->width;
|
||||
int32_t height = tex->height;
|
||||
const int32_t width = tex->width;
|
||||
const int32_t height = tex->height;
|
||||
|
||||
#if BAKE_VIDEO
|
||||
if (GLAD_WGL_NV_DX_interop2) {
|
||||
d3d_gl_fbo_tex.lock();
|
||||
d3d_gl_fbo_tex.lock();
|
||||
|
||||
gl_state_bind_framebuffer(d3d_gl_fbo_tex.fbo);
|
||||
gl_state_active_bind_texture_2d(0, tex->glid);
|
||||
gl_state_bind_sampler(0, rctx_ptr->render_samplers[1]);
|
||||
|
||||
if (nvenc_rgb) {
|
||||
GLint swizzle_rgb1[] = { GL_RED, GL_BLUE, GL_GREEN, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_rgb1);
|
||||
}
|
||||
|
||||
gl_state_set_viewport(0, 0, width, height);
|
||||
uniform_value[U_REDUCE] = 0;
|
||||
shaders_ft.set(SHADER_FT_REDUCE);
|
||||
rctx_ptr->render.draw_quad(width, height,
|
||||
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (nvenc_rgb) {
|
||||
GLint swizzle_rgba[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_rgba);
|
||||
}
|
||||
|
||||
gl_state_bind_sampler(0, 0);
|
||||
gl_state_bind_texture_2d(0);
|
||||
gl_state_bind_framebuffer(0);
|
||||
|
||||
d3d_gl_fbo_tex.unlock();
|
||||
gl_state_bind_framebuffer(d3d_gl_fbo_tex.fbo);
|
||||
gl_state_active_bind_texture_2d(0, tex->glid);
|
||||
gl_state_bind_sampler(0, rctx_ptr->render_samplers[1]);
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
d3d_gl_alpha_fbo_tex.lock();
|
||||
GLint swizzle_rgb1[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_rgb1);
|
||||
#endif
|
||||
|
||||
gl_state_bind_framebuffer(d3d_gl_alpha_fbo_tex.fbo);
|
||||
gl_state_active_bind_texture_2d(0, tex->tex);
|
||||
gl_state_set_viewport(0, 0, width, height);
|
||||
if (nvenc_rgb)
|
||||
shaders_dev.set(SHADER_DEV_CONVERT_RGB);
|
||||
else
|
||||
shaders_dev.set(SHADER_DEV_CONVERT_YCBCR_BT709);
|
||||
rctx_ptr->render.draw_quad(width, height,
|
||||
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
GLint swizzle_rgba[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_rgba);
|
||||
#endif
|
||||
|
||||
gl_state_bind_sampler(0, 0);
|
||||
gl_state_bind_texture_2d(0);
|
||||
gl_state_bind_framebuffer(0);
|
||||
|
||||
d3d_gl_fbo_tex.unlock();
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
d3d_gl_alpha_fbo_tex.lock();
|
||||
|
||||
gl_state_bind_framebuffer(d3d_gl_alpha_fbo_tex.fbo);
|
||||
gl_state_active_bind_texture_2d(0, tex->glid);
|
||||
|
||||
if (nvenc_rgb) {
|
||||
GLint swizzle_aaa1[] = { GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_aaa1);
|
||||
}
|
||||
|
||||
gl_state_set_viewport(0, 0, width, height);
|
||||
gl_state_set_viewport(0, 0, width, height);
|
||||
if (nvenc_rgb) {
|
||||
uniform_value[U_REDUCE] = 0;
|
||||
shaders_ft.set(SHADER_FT_REDUCE);
|
||||
rctx_ptr->render.draw_quad(width, height,
|
||||
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
else
|
||||
shaders_dev.set(SHADER_DEV_CONVERT_ALPHA);
|
||||
rctx_ptr->render.draw_quad(width, height,
|
||||
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
GLint swizzle_rgba[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
if (nvenc_rgb)
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_rgba);
|
||||
|
||||
gl_state_bind_texture_2d(0);
|
||||
gl_state_bind_framebuffer(0);
|
||||
gl_state_bind_texture_2d(0);
|
||||
gl_state_bind_framebuffer(0);
|
||||
|
||||
d3d_gl_alpha_fbo_tex.unlock();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
d3d_gl_alpha_fbo_tex.unlock();
|
||||
#endif
|
||||
|
||||
if (!GLAD_WGL_NV_DX_interop2) {
|
||||
void (*conv_func)(uint8_t * src, uint8_t * dst);
|
||||
|
||||
conv_func = [](uint8_t* src, uint8_t* dst) {
|
||||
@@ -6458,71 +6477,10 @@ bool x_pv_game::ctrl() {
|
||||
*(uint32_t*)dst = (temp & 0xFFFFFF) | (0xFF << 24);
|
||||
};
|
||||
|
||||
if (nvenc_rgb) {
|
||||
conv_func = [](uint8_t* src, uint8_t* dst) {
|
||||
const uint32_t temp = *(uint32_t*)src;
|
||||
*(uint32_t*)dst = (temp & 0xFF) | ((temp & 0xFF00) << 8)
|
||||
| ((temp & 0xFF0000) >> 8) | (0xFF << 24);
|
||||
};
|
||||
}
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
void (*conv_func_alpha)(uint8_t * src, uint8_t * dst);
|
||||
|
||||
conv_func_alpha = [](uint8_t* src, uint8_t* dst) {
|
||||
const uint32_t temp = *(uint32_t*)src;
|
||||
const uint32_t alpha = (temp >> 24) & 0xFF;
|
||||
*(uint32_t*)dst = alpha | (alpha << 8) | (alpha << 16) | (0xFF << 24);
|
||||
};
|
||||
|
||||
if (nvenc_rgb) {
|
||||
conv_func_alpha = [](uint8_t* src, uint8_t* dst) {
|
||||
const uint32_t temp = *(uint32_t*)src;
|
||||
const uint32_t alpha = (temp >> 24) & 0xFF;
|
||||
*(uint32_t*)dst = alpha | (alpha << 8) | (alpha << 16) | (0xFF << 24);
|
||||
};
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_res = {};
|
||||
HRESULT result = d3d_device_context->Map(d3d_texture,
|
||||
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_res);
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_alpha_res = {};
|
||||
HRESULT result_alpha = d3d_device_context->Map(d3d_alpha_texture,
|
||||
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_alpha_res);
|
||||
if (SUCCEEDED(result) && SUCCEEDED(result_alpha)) {
|
||||
gl_state_bind_texture_2d(tex->tex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_HALF_FLOAT, nvenc_temp_pixels.data());
|
||||
gl_state_bind_texture_2d(0);
|
||||
|
||||
uint8_t* src = (uint8_t*)nvenc_temp_pixels.data();
|
||||
uint8_t* dst = (uint8_t*)mapped_res.pData;
|
||||
uint8_t* dst_alpha = (uint8_t*)mapped_alpha_res.pData;
|
||||
|
||||
for (size_t y = 0, i = height; i; y++, i--) {
|
||||
uint8_t* src1 = &src[y * width * nvenc_src_pixel_size];
|
||||
uint8_t* dst1 = &dst[(height - y - 1) * width * nvenc_dst_pixel_size];
|
||||
uint8_t* dst1_alpha = &dst_alpha[(height - y - 1) * width * nvenc_dst_pixel_size];
|
||||
|
||||
for (size_t x = 0, j = width; j; x++, j--, src1 += nvenc_src_pixel_size,
|
||||
dst1 += nvenc_dst_pixel_size, dst1_alpha += nvenc_dst_pixel_size) {
|
||||
conv_func(src1, dst1);
|
||||
conv_func_alpha(src1, dst1_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
d3d_device_context->Unmap(d3d_texture, 0);
|
||||
d3d_device_context->Unmap(d3d_alpha_texture, 0);
|
||||
}
|
||||
else {
|
||||
if (SUCCEEDED(result))
|
||||
d3d_device_context->Unmap(d3d_texture, 0);
|
||||
if (SUCCEEDED(result_alpha))
|
||||
d3d_device_context->Unmap(d3d_alpha_texture, 0);
|
||||
}
|
||||
#else
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_res = {};
|
||||
if (SUCCEEDED(d3d_device_context->Map(d3d_texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_res))) {
|
||||
gl_state_bind_texture_2d(tex->glid);
|
||||
if (SUCCEEDED(d3d_device_context->Map(d3d_texture,
|
||||
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_res))) {
|
||||
gl_state_bind_texture_2d(d3d_gl_fbo_tex.tex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, nvenc_temp_pixels.data());
|
||||
gl_state_bind_texture_2d(0);
|
||||
|
||||
@@ -6540,6 +6498,29 @@ bool x_pv_game::ctrl() {
|
||||
|
||||
d3d_device_context->Unmap(d3d_texture, 0);
|
||||
}
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_alpha_res = {};
|
||||
if (SUCCEEDED(d3d_device_context->Map(d3d_alpha_texture,
|
||||
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_alpha_res))) {
|
||||
gl_state_bind_texture_2d(d3d_gl_alpha_fbo_tex.tex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, nvenc_temp_pixels.data());
|
||||
gl_state_bind_texture_2d(0);
|
||||
|
||||
uint8_t* src = (uint8_t*)nvenc_temp_pixels.data();
|
||||
uint8_t* dst = (uint8_t*)mapped_alpha_res.pData;
|
||||
|
||||
for (size_t y = 0, i = height; i; y++, i--) {
|
||||
uint8_t* src1 = &src[y * width * nvenc_src_pixel_size];
|
||||
uint8_t* dst1 = &dst[(height - y - 1) * width * nvenc_dst_pixel_size];
|
||||
|
||||
for (size_t x = 0, j = width; j; x++, j--,
|
||||
src1 += nvenc_src_pixel_size, dst1 += nvenc_dst_pixel_size)
|
||||
conv_func(src1, dst1);
|
||||
}
|
||||
|
||||
d3d_device_context->Unmap(d3d_alpha_texture, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7899,8 +7880,7 @@ bool x_pv_game::ctrl() {
|
||||
const int32_t height = BAKE_BASE_HEIGHT * BAKE_RES_SCALE;
|
||||
|
||||
#if BAKE_VIDEO
|
||||
nvenc_rgb = (nvenc_format == NVENC_ENCODER_RGB
|
||||
|| nvenc_format == NVENC_ENCODER_RGB_10BIT);
|
||||
nvenc_rgb = nvenc_format == NVENC_ENCODER_RGB || nvenc_format == NVENC_ENCODER_RGB_10BIT;
|
||||
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC tex_desc = {};
|
||||
@@ -7908,7 +7888,7 @@ bool x_pv_game::ctrl() {
|
||||
tex_desc.Height = height;
|
||||
tex_desc.MipLevels = 1;
|
||||
tex_desc.ArraySize = 1;
|
||||
tex_desc.Format = nvenc_rgb ? DXGI_FORMAT_AYUV : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
tex_desc.Format = DXGI_FORMAT_AYUV;
|
||||
tex_desc.SampleDesc.Count = 1;
|
||||
tex_desc.SampleDesc.Quality = 0;
|
||||
if (GLAD_WGL_NV_DX_interop2) {
|
||||
@@ -7929,12 +7909,10 @@ bool x_pv_game::ctrl() {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (GLAD_WGL_NV_DX_interop2) {
|
||||
d3d_gl_fbo_tex.init(d3d_texture);
|
||||
d3d_gl_fbo_tex.init(d3d_texture);
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
d3d_gl_alpha_fbo_tex.init(d3d_alpha_texture);
|
||||
d3d_gl_alpha_fbo_tex.init(d3d_alpha_texture);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!GLAD_WGL_NV_DX_interop2)
|
||||
nvenc_temp_pixels.resize((size_t)width * (size_t)height * nvenc_src_pixel_size);
|
||||
@@ -8035,12 +8013,10 @@ bool x_pv_game::ctrl() {
|
||||
delete nvenc_enc;
|
||||
nvenc_enc = 0;
|
||||
|
||||
if (GLAD_WGL_NV_DX_interop2) {
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
d3d_gl_alpha_fbo_tex.free();
|
||||
d3d_gl_alpha_fbo_tex.free();
|
||||
#endif
|
||||
d3d_gl_fbo_tex.free();
|
||||
}
|
||||
d3d_gl_fbo_tex.free();
|
||||
|
||||
#if BAKE_VIDEO_ALPHA
|
||||
d3d_alpha_texture->Release();
|
||||
@@ -10261,10 +10237,6 @@ XPVGameSelector::~XPVGameSelector() {
|
||||
bool XPVGameSelector::init() {
|
||||
start = false;
|
||||
exit = false;
|
||||
#if BAKE_VIDEO
|
||||
nvenc_format = NVENC_ENCODER_YUV420_10BIT;
|
||||
nvenc_lossless = false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10469,6 +10441,20 @@ void XPVGameSelector::window() {
|
||||
};
|
||||
|
||||
ImGui::ColumnComboBox("Format", nvenc_format_names, 6, (int32_t*)&nvenc_format, 0, false, &focus);
|
||||
|
||||
switch (nvenc_format) {
|
||||
case NVENC_ENCODER_YUV420:
|
||||
case NVENC_ENCODER_YUV444:
|
||||
case NVENC_ENCODER_RGB:
|
||||
ImGui::Checkbox("Lossless", &nvenc_lossless);
|
||||
break;
|
||||
case NVENC_ENCODER_YUV420_10BIT:
|
||||
case NVENC_ENCODER_YUV444_10BIT:
|
||||
case NVENC_ENCODER_RGB_10BIT:
|
||||
ImGui::Checkbox("Lossless (Will be saved at 8 bits!)", &nvenc_lossless);
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Lossless", &nvenc_lossless);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user